home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-09-14 | 145.3 KB | 6,623 lines | [TEXT/MPS ] |
-
- ;*******************************************************
- ;
- ; SCSI Driver Management Routines.
- ;
- ; Written by Matt Gulick. Started May 16,1988
- ;
- ; Copyright Apple Computer, Inc. 1988,89
- ;
- ;*******************************************************
-
- ;*******************************************************
- ;
- ; This file contains the subroutines needed by the
- ; SCSI Driver for things such as Getting RAM, Building
- ; data areas, calling outside routines for DIB
- ; management, as well as other generic routines that
- ; are used to make life easier for the driver. Also
- ; included in this file is the record definition for
- ; the DIB structure including all it's extensions.
- ;
- ;*******************************************************
-
- ;*******************************************************
- ;
- ; Revision History:
- ;
- ;*******************************************************
-
- ; May 16, 1988 File started.
- ; May 17, 1988 DIB Record defined.
- ; June 6, 1988 Main Driver Written.
- ; Jun 20, 1988 Update Input/Output Data in Comments
- ; Apr 14, 1989 Added Conditional Logic to remove
- ; block routines from character device
- ; assemblies.
-
- STRING PASCAL
- BLANKS OFF
- PAGESIZE 70
- PRINT NOGEN
- PRINT NOMDIR
- MACHINE M65816
-
- IMPORT master_uid
- IMPORT scsi_uid
- IMPORT scsi_mgrnum
- IMPORT rout2_s_disp
- IMPORT hndl_offset
- IMPORT buff_len
- IMPORT page_cnt
- IMPORT dpi_overide
- IMPORT call_type
- IMPORT main_drvr
- IMPORT internal
- ; IMPORT disk_switch
- IMPORT ram_page_cnt
- IMPORT internal_buff
- IMPORT default_dib
- IMPORT first_time
- IMPORT only_one
- IMPORT part_cnt
- IMPORT t_dvc_blocks
- IMPORT f_partition
- IMPORT part_num
- IMPORT vPart_cnt
- IMPORT rebuild
- IMPORT trash_it
- IMPORT direct_page
- IMPORT exit_dpage
- IMPORT gsos_dpage
- IMPORT saved_zp
- IMPORT valid
- IMPORT dvc_ram
- IMPORT sense_data
- IMPORT dvc_count
- IMPORT result
- IMPORT divend
- IMPORT divsor
- IMPORT max_blk_cnt
- IMPORT tot_dib_cnt
- IMPORT dib_data_struct
- IMPORT main_caller
- IMPORT curr_hndl
- IMPORT new_dib
- IMPORT scratch0
- IMPORT scratch1
- IMPORT scratch2
- IMPORT scratch3
- IMPORT killer_blk
- IMPORT auto_sense_data
- IMPORT temp_acc
- IMPORT pdi_flag
- IMPORT new_list
- IMPORT new_dib_cnt
- IMPORT new_dib_list
- IMPORT real_unit ;*************************
-
- IMPORT m_blk_size
- IMPORT m_blk_cnt
- IMPORT m_rslt
-
- ENTRY zero_mem
- ENTRY get_space
-
- ENTRY make_dib
- ENTRY find_empty
- ENTRY chk_ram
-
- ENTRY rebld_dibs
- ENTRY dibicise_new_ram
- ENTRY dibicise_new_dib
- ENTRY set_link_ptrs
- ENTRY major_update
- ENTRY minor_update
-
- ENTRY fix_unit_1
- ENTRY add_dib_ptr
- ENTRY do_post_install
-
- ENTRY read_pm_blk
- ENTRY pm_blk_num
- ENTRY chk_map
- ENTRY no_partition
- ENTRY check_map_entry
-
- ENTRY c_strt_buffer
- ENTRY c_strt_rqst_cnt
- ENTRY c_strt_blk_num
- ENTRY cache_valid
- ENTRY put_in_cache
- ENTRY get_from_cache
-
- ENTRY test_unit_rdy
- ENTRY read_capacity
-
- ENTRY start_unit
- ENTRY stop_unit
- ENTRY set_512_mode
-
- ENTRY notify_me
-
- ENTRY set_disk_sw
- ENTRY trash_volume
- ENTRY save_dp
- ENTRY restore_dp
- ENTRY set_our_dp
- ENTRY check_532_rw
- ENTRY munge_532
- ENTRY divide
-
- PRINT OFF
-
- INCLUDE 'scsihd.equates'
- INCLUDE 'M16.MEMORY'
- INCLUDE 'M16.UTIL'
- INCLUDE 'M16.MISCTOOL'
- PRINT ON
-
- EJECT
- ;____Mem_Manager_____
- ;*******************************************************
- ;
- ; This routine is used to Get a User ID from the
- ; memory manager for the SCSI Driver. This is
- ; required to get a userID for access reference.
- ;
- ; Inputs: None.
- ;
- ; Outputs: SCSID_uID = userID.
- ; Registers = Scrambled
- ;
- ; Errors: $0207 iderr Invalid userID.
- ;
- ;*******************************************************
-
- EXPORT get_mm_id
- get_mm_id PROC
- ;
- ; Get userID.
- ;
- pushword #$0000
-
- pushword #scsi_duid
-
- _GetNewID
- pla
- sta |master_uid
- sta |scsi_uid
- @rts rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; This routine is used to get the SCSI Manager Number
- ; from the Supervisory Dispatcher at startup time.
- ;
- ; Inputs: None.
- ;
- ; Outputs: scsi_mgrnum = SCSI Manager Number
- ; All Registers = scrambled
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT get_scsimgr
- get_scsimgr PROC
- ;
- ; Get userID.
- ;
- lda #$0000 ; Supervisor Driver Number (Unknown at this time)
- tax ; Supervisor Call Number ($0000)
- ldy #$0002 ; Spervisor ID for SCSI Manager ($0002)
- jsr |rout2_s_disp
- stx |scsi_mgrnum ; Preserve SCSI Driver Number for later use.
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'zero_mem'
- ;
- ; This routine will fill a section of memory with
- ; $00s.
- ;
- ; Inputs: Acc = Buffer Size
- ; X = Low Byte of new RAM Address
- ; Y = High Byte of new RAM Address
- ;
- ; Outputs: scsi_zp0 = Long Pointer to new RAM
- ; Address
- ; Acc = Scrambled
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT zero_mem
- zero_mem PROC
- ;
- ; Save the buffer size.
- ;
- sta @buff_size
- ;
- ; Setup MOVE_INFO call for a
- ; non-incrementing source and an
- ; incrementing destination.
- ;
- pushlong #null_buff ;Source
- phy ;Destination High Word
- phx ;Destination Low Word
- ;
- ; Restore buffer size. If = 0 then
- ; we are to do an entire bank or at
- ; least 64k bytes. This may cross
- ; banks.
- ;
- lda @buff_size
- beq @do_64k
- pea $0000
- pha
- bra @move_type
-
- @do_64k pea $0001
- pea $0000
-
- @move_type pea #move_scon_dinc
- jsl move_info
-
- @rts rts
- ;
- ; Data for this call
- ;
- @buff_size dc.w null
- null_buff dc.w null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; This routine is used to request a section of RAM from
- ; the memory manager for use by the driver. This
- ; routine allocates space for as requested by the byte
- ; count in the Acc.
- ;
- ; Inputs: Acc = Number of bytes requested.
- ; 0 = 1 bank
- ;
- ; Y = Offset to where the Handle
- ; should be stored within
- ; the allocated structure.
- ;
- ; Outputs: X = Low Word of new RAM Address
- ; Y = High Word of new RAM Address
- ; scsi_zp0 = Long Pointer to new RAM
- ; Address
- ; Acc = Scrambled
- ;
- ; Errors: Not enough memory if carry set.
- ;
- ;*******************************************************
-
- EXPORT get_space
- get_space PROC
- ;
- ; Request Acc bytes of RAM from
- ; Memory Manager.
- ;
- sty |hndl_offset
-
- pushlong #00000000 ;Space for result handle
-
- cmp $0000 ;Is it Null?
- beq @null ;Yes. Request 1 bank
-
- pushword #0000 ;Size in bytes of requested memory.
- bra @stuff_a
-
- @null pushword #0001 ;Request 1 bank
-
- @stuff_a sta |buff_len
- pha
-
- pushword scsi_uid ;Our User ID
-
- ;Attributes of requested mem.
- pea attrfixed++\
- attrnocross++\
- attrnospec++\
- attrpage
-
- pushlong #00000000 ;Location Pointer. Unused.
-
- _newhandle
-
- plx ; Get handle
- ply
-
- bcs @rts ; Exit if an error.
-
- ;
- ; Save Handle for later
- ;
- phy
- phx
- ;
- ; DEREF the Handle and get a
- ; pointer for the new RAM.
- ;
- stx <scsi_zp0
- sty <scsi_zp0+2
- ldy #$0002
- lda [scsi_zp0]
- tax
- lda [scsi_zp0],y
- tay
- ;
- ; Stuff pointer for indirect access.
- ;
- stx <scsi_zp0
- sty <scsi_zp0+2
- ;
- ; Call routine to zero out the
- ; new memory
- ;
- lda |buff_len
- jsr zero_mem
- ;
- ; Stuff Handle in RAM. Low byte first
- ;
- ldy |hndl_offset
- pullword [scsi_zp0],y
- iny
- iny
- pullword [scsi_zp0],y
- ;
- ; Restore X and Y to pointer status
- ;
- ldx <scsi_zp0
- ldy <scsi_zp0+2
- ;
- ; Clean Exit.
- ;
- clc
- @rts rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; This routine is used to request a section of RAM from
- ; the memory manager for use by the driver. This
- ; routine allocates space for the get_devices call to
- ; the SCSI Manager.
- ;
- ; Inputs: None.
- ;
- ; Outputs: dvc_list = Long Pointer to device List
- ; next_dib = Long Pointer to First DIB
- ; first_dib = Long Pointer to the beginning
- ; of the RAM Allocated for the
- ; new DIBs.
- ; Acc = Scrambled
- ;
- ; Errors: Not enough memory if carry set.
- ;
- ;*******************************************************
-
- EXPORT get_dvc_ram
- get_dvc_ram PROC
- ;
- ; Request the maximum device list
- ; size bytes of RAM from GS/OS
- ; System Service calls.
- ;
- lda #max_gdvc_buf+4 ; Allocate space for list.
- ldy #$0000
-
- ldx |direct_page ;If this is the first time, then
- bne @use_ours
- phx ;we don't want a DP setting of
- ;NULL
- ;
- ; Save away GS/OS Direct Page values
- ; until we have our own direct Page.
- ;
- jsr save_dp
-
- lda #max_gdvc_buf+4 ; Allocate space for list.
- ldy #$0000
-
- ldx |gsos_dpage
- stx |direct_page
-
- jsr |get_space
-
- pla ;Restore our settings preserving X & Y
- sta |direct_page
- sta |exit_dpage
- bra @over_use_ours
-
- @use_ours jsr |get_space
- ;
- ; Store newly allocated buffer
- ; pointer into the parm list for
- ; the get devices call. Account
- ; for the first 4 bytes that
- ; contain the handle associated
- ; with this memory segment.
- ;
- @over_use_ours bcs @rts_long
- clc
- txa
- sta |dvc_ram
- adc #$0004
- sta |dvc_buff
- sta <dvc_list
- tya
- sta |dvc_ram+2
- adc #$0000
- sta |dvc_buff+2
- sta <dvc_list+2
- ;
- ; Setup Pointer to our parm list
- ; in GS/OS Direct Page.
- ;
- ldx |gsos_dpage
- lda #get_dev_lst
- sta >smgr_pl_ptr,x
- lda #^get_dev_lst
- sta >smgr_pl_ptr+2,x
- ;
- ; Load registers with their
- ; required values.
- ;
- lda |scsi_mgrnum
- ldx #cmd_get_dvc
- jsr |rout2_s_disp
- @rts_long bcs @rts
- ;
- ; Restore our direct page Device List
- ;
- lda |dvc_buff
- sta <dvc_list
- lda |dvc_buff+2
- sta <dvc_list+2
- ;
- ; First word in [dvc_list}] contains
- ; the address of a 1 page area that
- ; we will be using for our direct
- ; page. Get it and move the
- ; 'dvc_list' pointer to our direct
- ; page area, but only if we have not
- ; yet done it.
- ;
- lda |direct_page
- bne @we_did_it ;It's already been done.
-
- lda [dvc_list]
- tax
- lda <dvc_list
- sta >dvc_list,x
- lda <dvc_list+2
- sta >dvc_list+2,x
- txa
- sta |direct_page
- sta |exit_dpage
- ;
- ; Set our Direct Page with the first
- ; 'x' Bytes equal to the GS/OS DP
- ; settings.
- ;
- ;
- clc ; Calculate Source Address of GS/OS
- tdc ; Direct Page that we want.
- sta |gsos_dpage ; Preserving GS/OS DP for later use.
- adc #dev_num
- pea $0000
- pha
- ;
- clc ; Calculate Destination Address of
- lda |direct_page ; our Direct Page that we want.
- adc #dev_num
- pea $0000
- pha
-
- pushlong #dib_ptr+4 ;Length of the move
-
- pushword #move_sinc_dinc
-
- jsl move_info ;Move the data
- ;
- ; Restore the Direct Page that we
- ; borrowed until this was done.
- ;
- jsr restore_dp
- ;
- ; Set our Direct Page.
- ;
- lda |direct_page
- tcd
- ;
- ; Check for zero Devices.
- ;
- @we_did_it ldy #$0002
- lda [dvc_list],y
- beq @no_devices
- ;
- ; Ensure that device count is
- ; in range.
- ;
- cmp #$0100+1 ;No more than 256 devices
- blt @count_ok
- lda #max_dvc_cnt ;Max Count
- @count_ok sta |dvc_count
- jsr |make_dib
- stx <next_dib
- stx <first_dib
- sty <next_dib+2
- sty <first_dib+2
-
- lda #no_error
- clc
- ;
- ; Restore the Direct Page that we
- ; borrowed until this was done.
- ;
- @rts pha
- php
- jsr restore_dp
- plp
- pla
- rts
- ;
- ; No Devices Error.
- ;
- ; Restore the Direct Page that we
- ; borrowed until this was done.
- ;
- @no_devices jsr restore_dp
- lda #drvr_no_dev
- sec
- rts
-
- get_dev_lst dc.w scsi_dtype
- dc.l notify_me
- dvc_buff dc.l null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; This routine is the inverse of the above routine.
- ; It calls the memory manager to deallocate the space
- ; we used to request the device list from the SCSI
- ; manager.
- ;
- ; Inputs: X = Low byte of Buffer pointer
- ; Y = High byte of Buffer pointer
- ;
- ; Outputs: All Regs = Scrambled
- ;
- ; Errors: Not enough memory if carry set.
- ;
- ;*******************************************************
-
- EXPORT fre_dvc_ram
- fre_dvc_ram PROC
- ;
- ; Remove the device list from
- ; active use and free the mem.
- ;
- ; Stuff pointer for indirect access.
- ;
- lda |dvc_ram
- sta <scsi_zp0
- lda |dvc_ram+2
- sta <scsi_zp0+2
-
- ldy #$0002 ;High byte first on stack
- pushword [scsi_zp0],y
- pushword [scsi_zp0]
-
- _disposehandle
-
- rts
-
- ENDP
-
- EJECT
-
- ;____DIB_Mem_Mgr_____
- ;*******************************************************
- ;
- ; This routine is used to request a section of RAM from
- ; the memory manager for use by the driver. This
- ; routine allocates space for 1 DIB.
- ;
- ; Inputs: Acc = $00xx = DIB Count.
- ; Null = $0100
- ;
- ; Outputs: X = Low Byte of new RAM Address
- ; Y = High Byte of new RAM Address
- ; scsi_zp0 = Long Pointer to new RAM
- ; Address
- ; Acc = Scrambled
- ;
- ; Errors: Not enough memory if carry set.
- ;
- ;*******************************************************
-
- EXPORT make_dib
- make_dib PROC
- ;
- ; Request $100 bytes of RAM for
- ; each DIB from GS/OS System
- ; Service calls.
- ;
- and #$00ff
- sta |ram_page_cnt
- xba ;Cheap multiply by $0100
- ldy #dib.handle ;Offset to where we want the handle
- jsr |get_space ;Allocate space for DIBs.
- bcc @rts
- stz |ram_page_cnt
- @rts rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; This routine is called via a 'jsl' and returns the
- ; page number of the caller in X and Y with X being
- ; the low byte. This is intended for use by the
- ; completion routines in the DIB as a tool to find
- ; the DIB's starting location in memory
- ;
- ; Inputs: None.
- ;
- ; Outputs: X = Low byte of callers page
- ; Y = High byte of callers page
- ; Acc = Scrambled
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT g_dib_ptr
- g_dib_ptr PROC
- ;
- ; Get the callers return
- ; address from the stack,
- ; strip down to a page number,
- ; transfer to X and Y and
- ; return to caller via an 'rtl'
- ;
- lda <1,s
- sec
- sbc #dib.complet+3-dib.linkptr
- tax
- lda <3,s
- and #$00ff
- tay
- rtl
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'ADD_DIB_RAM'
- ;
- ; This routine searches for the last DIB for this
- ; driver, allocates enough ram for 4 additional DIBs
- ; and links them in.
- ;
- ; Inputs: dib_ptr = Last DIB in Device link
- ; add_dib_here = Where the new DIB is to be built
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if not enough memory
- ;
- ;*******************************************************
-
- EXPORT add_dib_ram
- add_dib_ram PROC
- ;
- ; 'ADD_DIB_HERE' Pointer now points
- ; to the last DIB currently allocated
- ; and preserve location of last DIB.
- ;
- lda <add_dib_here
- sta <last_dib
- pha ;Save and later restore
- lda <add_dib_here+2
- sta <last_dib+2
- pha ;Save and later restore
- ;
- ; Get some RAM for a few more DIBs..
- ;
- lda #dibs_2_make
- jsr make_dib
- bcc @over_0
- ;
- ; Got an Error. Fix the Stack and Exit.
- ;
- tax
-
- pla ;Saved, and now restore
- sta <last_dib+2
- pla ;Saved, and now restore
- sta <last_dib
-
- txa
-
- rts
- ;
- ; Do First link
- ;
- @over_0 sty <first_dib+2
- stx <first_dib
- ;
- ; Dibicise first new DIB in the new
- ; Memory.
- ;
- sec ;Don't do the links.
- jsr dibicise_new_ram
- ;
- ; Do the Head and Forward links also.
- ;
- lda #null
- ldy #dib.headlnk
- sta [first_dib],y
-
- ldy #dib.fdvclnk
- sta [first_dib],y
-
- ldy #dib.unitnum ;Don't forget the unit number
- sta [first_dib],y
- ;
- ; Finalise the new DIB Structure.
- ;
- dec |main_caller
- ;********
- ;******** 6/12/89 Begin fix MSG
- ;******** rebuild flag being destroyed.
- ;********
- lda |rebuild ;The state of this flag must be preserved.
- pha
- stz |rebuild ;Set to zero. (Full Rebuild)
-
- jsr set_link_ptrs ;Now we do the links.
-
- pla
- sta |rebuild ;Restore the callers state for this flag.
-
- ; stz |rebuild ;Set to zero. (Full Rebuild)
-
- ; jsr set_link_ptrs ;Now we do the links.
- ;********
- ;******** 6/12/89 End fix MSG
- ;******** rebuild flag being destroyed.
- ;********
- ;
- ; Finish the last three links. They
- ; live in the new memory segment.
- ;
- lda #dibs_2_make-1
- sta @loop_cnt
-
- @link_loop clc
-
- lda <next_dib
- sta <last_dib
- adc #dib_size
- sta <next_dib
-
- lda <next_dib+2
- sta <last_dib+2
- adc #^dib_size
- sta <next_dib+2
-
- dec |main_caller
- ;********
- ;******** 6/12/89 Begin fix MSG
- ;******** rebuild flag being destroyed.
- ;********
- lda |rebuild ;The state of this flag must be preserved.
- pha
- stz |rebuild ;Set to zero. (Full Rebuild)
-
- jsr dibicise_new_dib
-
- pla
- sta |rebuild ;Restore the callers state for this flag.
-
- ; stz |rebuild
-
- ; jsr dibicise_new_dib
- ;********
- ;******** 6/12/89 End fix MSG
- ;******** rebuild flag being destroyed.
- ;********
- dec @loop_cnt
- bne @link_loop
- ;
- ; Clean Exit
- ;
- ; Reinitialise mem_dib_cnt to zero.
- ;
- lda #null
- ldy #dib.mem_dib_cnt
- sta [first_dib],y
- ;
- ; Wipe out last link pointer to no where.
- ;
- sta [next_dib]
- ldy #dib.linkptr+2
- sta [next_dib],y
-
- pla ;Saved, and now restore
- sta <last_dib+2
- pla ;Saved, and now restore
- sta <last_dib
-
- clc
- rts
- ;
- ; Data Area.
- ;
- @loop_cnt dc.w null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; FIND_EMPTY
- ;
- ; This routine serches forward from the current DIB
- ; looking for an empty. If it exits with the carry
- ; clear, then one has been found. If the carry is
- ; set, then it points to the last DIB in the linked
- ; list and found non empty.
- ;
- ; Inputs: <DIB_PTR = Last DIB Location
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: <ADD_DIB_HERE = Empty DIB if found
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if no empties were found
- ;
- ;*******************************************************
-
- EXPORT find_empty
- find_empty PROC
- ;
- ; Are we at the last DIB? Set beginning
- ; pointer for check.
- ;
- lda <dib_ptr
- sta <last_dib
- sta <add_dib_here
- lda <dib_ptr+2
- sta <last_dib+2
- sta <add_dib_here+2
- ;
- ; Are we at the last DIB? (LOOP)
- ;
- @fnd_empty_lup ldy #$0002
- lda [add_dib_here]
- tax
-
- lda [add_dib_here],y;Should never be in Bank $00
- bne @advance_ptr ;No.
-
- @sec sec ;Yes. Exit
- rts
- ;
- ; Advance Ptr to next DIB.
- ;
- @advance_ptr sta <add_dib_here+2
- stx <add_dib_here
- ;
- ; Is it Free?
- ;
- ; Must have a zero Head Link Ptr,
- ; Forward Device Link Ptr, and
- ; DIB Device Number to be considered
- ; free.
- ;
- ldy #dib.devnum
- lda [add_dib_here],y
- bne @fnd_empty_lup ;No. Check next one.
-
- ldy #dib.headlnk
- lda [add_dib_here],y
- bne @fnd_empty_lup ;No. Check next one.
-
- ldy #dib.fdvclnk
- lda [add_dib_here],y
- bne @fnd_empty_lup ;No. Check next one.
- ;
- ; Make the DIB Device Number non-zero
- ; to prvent it from being selected
- ; again before it is started up by
- ; the operating system.
- ;
- ldy #dib.devnum
- lda [add_dib_here],y
- inc a
- sta [add_dib_here],y
-
- clc ;Yes. Exit
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'chk_ram'
- ;
- ; This routine checks to see if we have any room left
- ; in this memory segment for another DIB. If not then
- ; the memory manager is called and the new RAM is
- ; dibicised.
- ;
- ; Inputs: Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Carry = 1
- ; Acc = Error
- ; Carry = 0
- ; Acc = ram_page_cnt
- ; = 0 no more devices
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
- ;
- ; Start of the code segment for this.
- ;
- EXPORT chk_ram
- chk_ram PROC
- ;
- ; All done with the DIB Update now
- ; do we have any more RAM left to
- ; build further DIBs?
- ;
- dec |ram_page_cnt
- bne @adv_ptrs ;Yes we do. Continue on.
-
- ;
- ; Account for 'part_cnt' being equal
- ; to the Actual Partition Count - 1
- ;
- sec
- ; clc ;Bug Fix 4/3/89
-
- lda |dvc_count ;No we don't. Get the remaining device
- adc |part_cnt ;count and add the remaining Part count
- ; dec a ;Subtract our current working device
- ; dec a ;Subtract our current working DIB
- beq @exit ;Are we done? Yes.
- bmi @exit ;Yes.
- cmp #$00ff+1 ;No. Bound check the result and
- blt @call_make_dib
-
- @set_max lda #$00ff ;Set to max if greater.
- @call_make_dib jsr make_dib ;Call routine to make the DIB RAM
- bcc @update_new ;available. ERROR?
- cmp #drvr_no_dev ;Yes. Then Exit
- bne @sec
- clc
- rts
- @sec sec
- rts
- ;
- ; We had room in the current RAM
- ; Space so we will advance all the
- ; pointers to their next values
- ; within that space.
- ;
- @adv_ptrs clc
- lda <next_dib
- sta <last_dib
- adc #dib_size
- sta <next_dib
- lda <next_dib+2
- sta <last_dib+2
- adc #^dib_size
- sta <next_dib+2
- jsr dibicise_new_dib
- bra @exit
- ;
- ; We have a new memory segment so
- ; we need to account for this when
- ; we advance our pointers.
- ;
- @update_new stx <first_dib
- sty <first_dib+2
- lda <next_dib
- sta <last_dib
- lda <next_dib+2
- sta <last_dib+2
- clc ;Do Links Also
- jsr dibicise_new_ram
- ;
- ; Clean exit.
- ;
- @exit lda |ram_page_cnt
- clc
- rts
-
- ENDP
-
- EJECT
-
- ;____DIB_Building____
- ;*******************************************************
- ;
- ; REBLD_DIBS
- ;
- ; It is the function of this routine to blindly
- ; rebuild the DIBs for the physical device attached to
- ; the current DIB. If that device is non-partitioned,
- ; then only one DIB will be built, and a DISK SWITCHED
- ; will be issued. If there are more than one device,
- ; as in partitioned media, then all the DIBs for the
- ; partitions will be re-built. This is treated as if
- ; the device just came online for the first time. If
- ; the new device has fewer partitions than there are
- ; DIBs that are already allocated, then the left over
- ; will be marked as being offline. If, on the other
- ; hand, there are more partitions than DIBs, then new
- ; ones will be allocated and built. These will then be
- ; permanantly linked to that physical device.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if operation could not be
- ; completed. Out of memory for example.
- ;
- ;*******************************************************
- ;
- ; Start of the code segment for this.
- ;
- EXPORT rebld_dibs
- rebld_dibs PROC
- ;
- ; Clear Linked Device Flag. This will
- ; account for the situation where a
- ; partitioned disk has been reduced to
- ; a single volume.
- ;
- stz @linked
- ;
- ; Zero the count of new devices to be
- ; started.
- ;
- stz |new_dib_cnt
- ;
- ; Point to first DIB in link if any.
- ; If it is zero, then we are already
- ; there.
- ;
- ldy #dib.headptr+2
- lda [dib_ptr],y
- ldy #dib.headptr
- ora [dib_ptr],y
- beq @over
- ;
- ; It's non-zero. Set up DIB_PTR
- ;
- lda [dib_ptr],y
- tax
- ldy #dib.headptr+2
- lda [dib_ptr],y
- sta <dib_ptr+2
- stx <dib_ptr
- ;
- ; Set Temp Pointer to first DIB in the link.
- ;
- @over lda <dib_ptr
- sta <scsi_zp6
- lda <dib_ptr+2
- sta <scsi_zp6+2
- ;
- ; Mark each DIB in the link as offline
- ; and switched.
- ;
- @loop ldy #dib.dvcflag
- lda [scsi_zp6],y
- and #(dvc_online++\
- pdos_part)--\
- $ffff
- ora #dvc_switch++\
- dvc_hardofl
- sta [scsi_zp6],y
- ;
- ; Mark each DIB in the link as Unlinked.
- ;
- ldy #dib.dvcchar
- lda [scsi_zp6],y
- and #linked_dvc--\
- $ffff
- sta [scsi_zp6],y
- ;
- ; Zero Partition Offset for each DIB
- ;
- lda #null
- ldy #dib.start_blk
- sta [scsi_zp6],y
- ldy #dib.start_blk+2
- sta [scsi_zp6],y
- ;
- ; It's non-zero. Set up next DIB_PTR
- ;
- clc
- ldy #dib.fdvcptr
- lda [scsi_zp6],y
- tax
- beq @null
-
- sec
-
- @null ldy #dib.fdvcptr+2
- lda [scsi_zp6],y
- bne @doit
- bcc @over_0
-
- @doit sta <scsi_zp6+2
- stx <scsi_zp6
-
- bra @loop
- ;
- ; Initialize a few values.
- ;
- @over_0 lda #$ffff ;The following values will be incrimented
- sta |first_time ;with zero indicating special action.
- sta |rebuild ;This is set to $ffff so that it will only
- sta |only_one ;occur on the first pass through.
-
- stz |part_cnt
- stz |pm_blk_num
- stz |new_dib
- ;
- ; MAIN LOOP OF CODE SEGMENT.
- ;
- @main_loop jsr read_pm_blk
- bcc @with_data ;This device is with data
- lda auto_sense_data+\ ;Is it an audio disk?
- rqst_sens.addnl_sens_code
- and #$00fe ;Checking for $84, $64, or $63
- cmp #$0064 ;This cover $63, $64
- beq @single
- cmp #$0084
- beq @single
- sec
- rts ;There was an error!
- ;
- ; Valid Partition Map?
- ;
- @with_data jsr chk_map
- bcs @done
- bne @main
- ;
- ; We have a vaild Partition Map so
- ; we need to make an entry for each
- ; partition other than those with
- ; the partition types of 'MAP',
- ; 'SCRATCH', and 'FREE'. All others
- ; will be considered valid. We also
- ; only accept up to 'max_partitions'
- ; partitions per disk.
- ;
- ; How many partitions are there?
- ;
- lda |pm.MapBlkCnt\
- +internal_buff
- bne @force_max
- lda |pm.MapBlkCnt+2\
- +internal_buff
- xba ;Value is High --> Low
- cmp #max_partitions+1
- blt @cnt_ok
- @force_max lda #max_partitions
- @cnt_ok sta |part_cnt
-
- cmp #$0002+1
- blt @non_linked
- dec @linked
- @non_linked dec |part_cnt
- bpl @main
- ;
- ; No valid entry. Set as if no
- ; partitions.
- ;
- jsr no_partition
- jsr trash_volume ;Trash the volume if caller wishes.
- ;See |trash_it flag in trash_volume
- ;
- ; Mark DIB as online and switched.
- ;
- @single ldy #dib.dvcflag
- lda [dib_ptr],y
- and #dvc_hardofl--\
- $ffff
- ora #dvc_switch++\
- dvc_online
- sta [dib_ptr],y
-
- lda #null
- clc
- rts
- ;
- ; Check validity of partiton map.
- ;
- @main jsr check_map_entry
- bcc @chk_pdos
- ;
- ; It was undefined or unusable
- ;
- ; Is the Pointer good?
- ;
- ; Is it a cold DIB?
- ;
- ldy #dib.dvcflag
- lda [add_dib_here],y
- and #cold_dib
- beq @over_cold ;No. Skip clear code.
- ;
- ; Mark DIB to the Default.
- ;
- ldy #dib.dvcflag
- lda #wait_mode++\ ; Wait Mode is default
- cold_dib ; and they start cold.
- sta [add_dib_here],y
- ;
- ; Must set Head Link Ptr, Forward
- ; Device Link Ptr, and DIB Device
- ; Number to Null.
- ;
- lda #null
-
- ldy #dib.devnum
- sta [add_dib_here],y
-
- ldy #dib.headlnk
- sta [add_dib_here],y
-
- ldy #dib.fdvclnk
- sta [add_dib_here],y
- ;
- ; And skip it.
- ; Is there more to do?
- ;
- @over_cold dec |part_cnt
- bmi @do_dpi ;No!
- jmp @main_loop ;Yes!
- ;
- ; Check to see if the post driver install
- ; list contains any entries.
- ;
- @do_dpi jsr do_post_install
- ;
- ; Check the only one flag. If true
- ; then unlink it.
- ;
- lda |only_one
- bne @done
-
- ldy #dib.dvcchar
- lda [rebuild_zp],y
- and #linked_dvc--\
- $ffff
- sta [rebuild_zp],y
- ;
- ; Clean exit.
- ;
- @done clc
- @rts rts
- ;
- ; Check the Overflow bit. If it is set,
- ; then this is a ProDOS Partition and we
- ; need to set the correct bit in the DIB.
- ;
- @chk_pdos bvc @over_1
- ;
- ; Set the ProDOS Bit.
- ;
- ldy #dib.dvcflag
- lda [dib_ptr],y
- ora #pdos_part
- sta [dib_ptr],y
- ;
- ; Issue call to fix unit 1. This will
- ; guarantee that the first unit is also
- ; the first ProDOS Partition on the disk.
- ;
- jsr fix_unit_1
- ;
- ; Get the Block Count for this
- ; Partition and store it in the
- ; DIB. The count as it exists
- ; in the partition data is stored
- ; High byte to Low byte. We will
- ; need to alter this to Low --> High
- ; format.
- ;
- @over_1 ldy #dib.blkcnt
- lda |pm.PartBlkCnt+2\
- +internal_buff
- xba
- sta [dib_ptr],y
- ldy #dib.blkcnt+2
- lda |pm.PartBlkCnt\
- +internal_buff
- xba
- sta [dib_ptr],y
- ;
- ; Now we need to get the starting
- ; location for this partition. This
- ; will be added to the requested
- ; block to generate a real block
- ; address. Also in High --> Low format.
- ;
- ldy #dib.start_blk+2
- lda |pm.PyPartStart+2\
- +internal_buff
- sta [dib_ptr],y
- ldy #dib.start_blk
- lda |pm.PyPartStart\
- +internal_buff
- sta [dib_ptr],y
- ;
- ; Get Location of this partition on disk.
- ;
- ldy #dib.part_blk
- lda |pm_blk_num
- sta [dib_ptr],y
- ;
- ; Mark DIB as online and switched.
- ;
- ldy #dib.dvcflag
- lda [dib_ptr],y
- and #dvc_hardofl--\
- $ffff
- ora #dvc_switch++\
- dvc_online
- sta [dib_ptr],y
- ;
- ; Mark DIB as Linked.
- ;
- lda @linked
- bpl @skip_link
- ldy #dib.dvcchar
- lda [dib_ptr],y
- ora #linked_dvc
- sta [dib_ptr],y
- ;
- ; Inc the ONLY_ONE Flag. If it is
- ; null then save the dib_ptr. On
- ; exit we will check this flag and
- ; if = 0 we will use this pointer
- ; to clear the linked flag.
- ;
- inc |only_one
- bne @skip_link
-
- lda <dib_ptr
- sta <rebuild_zp
- lda <dib_ptr+2
- sta <rebuild_zp+2
- ;
- ; Wipe out block 2 of partition or
- ; volume
- ;
- @skip_link jsr trash_volume
- ;
- ; Is this a new dib?
- ;
- bit |new_dib
- bpl @set_dsw ;No. Set disk switch
-
- ldx <dib_ptr
- ldy <dib_ptr+2
- jsr add_dib_ptr ;Yes. Add to the list for post driver
- bra @over_dsw ; install.
- ;
- ; Set the DISK SWITCHED
- ;
- @set_dsw
- ; jsr set_disk_sw
- ;
- ; Is there more to do?
- ;
- @over_dsw stz |new_dib
- dec |part_cnt
- bpl @over_do_dpi ;Yes!
- jmp @do_dpi ;No!
- ;
- ; All done with the DIB Update now
- ; do we have any more DIBs, for this
- ; linked device?
- ;
- @over_do_dpi ldy #dib.fdvcptr
- lda [dib_ptr],y
- tax
-
- ldy #dib.fdvcptr+2
- ora [dib_ptr],y
- beq @over_2
- lda [dib_ptr],y
-
- sta <dib_ptr+2
- stx <dib_ptr
- ;
- ; Do the next one.
- ;
- @jmp_main jmp @main_loop
- ;
- ; It's zero. Need to add DIBs
- ;
- ; Is there an empty DIB some where?
- ;
- @over_2 jsr find_empty
- bcc @found_empty
- ;
- ; Get room for some more DIBs.
- ;
- jsr add_dib_ram
- bcc @over_2
-
-
- rts
- ;
- ; We need to set some pointers for
- ; the routines that we will be
- ; calling. These pointers are similar
- ; to those used in the startup code
- ;
- ; 1st. Set the pointer to the next
- ; DIB to be build.
- ;
- @found_empty lda <add_dib_here
- sta <dib_ptr
- sta <next_dib
- lda <add_dib_here+2
- sta <dib_ptr+2
- sta <next_dib+2
- ;
- ; Preserve the Link Pointer. Otherwise
- ; it will be destroyed by the dibicise
- ; routine.
- ;
- ldy #dib.linkptr+2
- lda [next_dib]
- pha
- lda [next_dib],y
- pha
- ;
- ; Set the 'first_dib' pointer to the
- ; first dib in the same memory segment
- ; from the memory manager as the one
- ; that contains the space to be used
- ; for this new dib. first we get the
- ; handle.
- ;
- ldy #dib.handle
- lda [next_dib],y
- sta <first_dib
-
- ldy #dib.handle+2
- lda [next_dib],y
- sta <first_dib+2
- ;
- ; then we deref the handle.
- ;
- ldy #$0002
- lda [first_dib]
- tax
- lda [first_dib],y
- sta <first_dib+2
- stx <first_dib
- ;
- ; Tell the dibicize routine that this
- ; is not from the startup code. This
- ; also forces the descriptive names
- ; minor id to be changed leaving the
- ; major or device portion as it is.
- ;
- dec |main_caller
- ;
- ; Dibicise the new dib.
- ;
- jsr dibicise_new_dib
- ;
- ; Restore the Link Pointer. Otherwise
- ; it is destroyed by the dibicise
- ; routine.
- ;
- ldy #dib.linkptr+2
- pla
- sta [next_dib],y
- pla
- sta [next_dib]
- ;
- ; Rev the unit number to be unique
- ;
- ldy #dib.unitnum
- lda [next_dib],y
- tax
- and #max_p_mask
- cmp #max_p_mask
- beq @all_done
-
- txa
- clc
- adc #p_mask_adder
- sta [next_dib],y
- ;
- ; This flag indicates that this is a
- ; new dib and that the routine that
- ; finalizes this dib will have to
- ; issue a post driver install call.
- ;
- dec |new_dib
- ;
- ; Go back to the main loop where this
- ; dib will be finalized and installed.
- ;
- jmp @main_loop
- ;
- ; Clean Exit
- ;
- @all_done clc
- rts
- ;
- ; Misc Data for this sub-routine
- ;
- @linked dc.w null
- @part_num dc.w null
- @vPart_cnt dc.w null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'do_part_dib'
- ;
- ; This routine issues a READ call to the device and
- ; then uses the data returned to check for any
- ; partitions on the media. If partitions do exist, it
- ; then creates the needed dibs from those that have
- ; been allocated but unused, or if needed will create
- ; a new memory segment and continue on.
- ;
- ; Inputs: <next_dib = Next DIB start (LONG)
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: <next_dib = last DIB Built (LONG)
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
- ;
- ; Start of the code segment for this.
- ;
- EXPORT do_part_dib
- do_part_dib PROC
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;
- ; MAIN LOOP OF CODE SEGMENT.
- ;
- @main_loop jsr read_pm_blk
- bcc @chk_map ;Was there an error?
-
- jsr no_partition ;
- bra @done
- ; Valid Partition Map?
- ;
- @chk_map jsr chk_map
- bcs @done
- bne @main
- ;
- ; We have a vaild Partition Map so
- ; we need to make an entry for each
- ; partition other than those with
- ; the partition types of 'MAP',
- ; 'SCRATCH', and 'FREE'. All others
- ; will be considered valid. We also
- ; only accept up to 'max_partitions'
- ; partitions per disk.
- ;
- ; How many partitions are there?
- ;
- lda |pm.MapBlkCnt\
- +internal_buff
- bne @force_max
- lda |pm.MapBlkCnt+2\
- +internal_buff
- xba ;Value is High --> Low
- cmp #max_partitions+1
- blt @cnt_ok
- @force_max lda #max_partitions
- @cnt_ok sta |part_cnt
-
- dec |part_cnt
- bpl @main
- ;
- ; No valid entry. Set as if no
- ; partitions.
- ;
- jsr no_partition
- clc
- rts
- ;
- ; Check validity of partiton map.
- ;
- @main jsr check_map_entry
- bcc @chk_pdos
- ;
- ; It was undefined or unusable
- ; Mark DIB to the Default.
- ;
- ldy #dib.dvcflag
- lda #wait_mode++\ ; Wait Mode is default
- cold_dib ; and they start cold.
- sta [next_dib],y
- ;
- ; Must set Head Link Ptr, Forward
- ; Device Link Ptr, and DIB Device
- ; Number to Null.
- ;
- lda #null
-
- ldy #dib.devnum
- sta [next_dib],y
-
- ldy #dib.headlnk
- sta [next_dib],y
-
- ldy #dib.fdvclnk
- sta [next_dib],y
- ;
- ; And skip it.
- ; Is there more to do?
- ;
- dec |part_cnt
- bpl @main_loop
- ;
- ; Clean exit.
- ;
- @done clc
- @rts rts
- ;
- ; Check the Overflow bit. If it is set,
- ; then this is a ProDOS Partition and we
- ; need to set the correct bit in the DIB.
- ;
- @chk_pdos bvc @over
- ;
- ; Set the ProDOS Bit.
- ;
- ldy #dib.dvcflag
- lda [next_dib],y
- ora #pdos_part
- sta [next_dib],y
- ;
- ; Issue call to fix unit 1. This will
- ; guarantee that the first unit is also
- ; the first ProDOS Partition on the disk.
- ;
- jsr fix_unit_1
- ;
- ; Get the Block Count for this
- ; Partition and store it in the
- ; DIB. The count as it exists
- ; in the partition data is stored
- ; High byte to Low byte. We will
- ; need to alter this to Low --> High
- ; format.
- ;
- @over ldy #dib.blkcnt
- lda |pm.PartBlkCnt+2\
- +internal_buff
- xba
- sta [next_dib],y
- ldy #dib.blkcnt+2
- lda |pm.PartBlkCnt\
- +internal_buff
- xba
- sta [next_dib],y
- ;
- ; Now we need to get the starting
- ; location for this partition. This
- ; will be added to the requested
- ; block to generate a real block
- ; address. Also in High --> Low format.
- ;
- ldy #dib.start_blk+2
- lda |pm.PyPartStart+2\
- +internal_buff
- sta [next_dib],y
- ldy #dib.start_blk
- lda |pm.PyPartStart\
- +internal_buff
- sta [next_dib],y
- ;
- ; Get Location of this partition on disk.
- ;
- ldy #dib.part_blk
- lda |pm_blk_num
- sta [next_dib],y
- ;
- ; Set this device to ONLINE.
- ;
- ldy #dib.dvcflag
- lda [next_dib],y
- ora #dvc_online
- sta [next_dib],y
- ;
- ; Increment the partition count.
- ;
- inc |part_num
- beq @chk_ram
- ;
- ; Update the High seven bits of the
- ; unit number checking for the max
- ; value of 'max_partitions'.
- ;
- ldy #dib.unitnum
- lda [next_dib],y
- tax
- and #max_p_mask
- cmp #max_p_mask
- beq @all_done
- txa
- clc
- adc #p_mask_adder
- sta [next_dib],y
- inc |vPart_cnt
- ;
- ; All done with the DIB Update now
- ; do we have any more DIBs, and if
- ; so, do we have any more RAM left
- ; to build further DIBs?
- ;
- @chk_ram dec |part_cnt
- bmi @all_done
- dec |main_caller
- jsr chk_ram
- bcs @bad_call ;ERROR?
- jmp @main_loop ;No. Do the next one.
- @bad_call cmp #drvr_no_dev ;Yes. Then Exit
- bne @sec
- clc
- rts
- @sec sec
- rts
- ;
- ; Clean Exit
- ;
- @all_done clc
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- ;
- ; Clean Exit
- ;
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'dibicise_new_ram'
- ;
- ; This routine takes the DIB located at [last_dib] and
- ; copies it into the new ram space. It does this
- ; while preserving the handle at offset 'dib.handle'.
- ; By so doing, it will be possible to free this ram
- ; space at some later time if that is deemed correct.
- ;
- ; Inputs: <last_dib = Last DIB built (LONG)
- ; <first_dib = Pointer to new (LONG)
- ; ram space.
- ; Acc = Unspecified
- ; Carry Clear = Do Link Pointers
- ; Set = Skip Link Pointers
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: <last_dib = unchanged (LONG)
- ; <first_dib = unchanged (LONG)
- ; <next_dib = <first_dib (LONG)
- ; |curr_hndl = Handle for new ram (LONG)
- ;
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; If Carry Set on entry then
- ;
- ; |tot_dib_cnt = $0000 (WORD)
- ;
- ; If Carry Clear on entry then
- ;
- ; [last_dib] = points to this DIB (LONG)
- ; [first_dib] = defaults set (PTR)
- ; 'Int Pntrs' = Set to this DIB (LONG)s
- ; 'dispname' = Device Name (STR)
- ; |tot_dib_cnt = # of valid DIBs (WORD)
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT dibicise_new_ram
- dibicise_new_ram PROC
- ;
- ; Save Do Links Flag.
- ;
- php
- ;
- ; Preserve Handle for this
- ; memory segment.
- ;
- ldy #dib.handle
- lda [first_dib],y
- sta |curr_hndl
- ldy #dib.handle+2
- lda [first_dib],y
- sta |curr_hndl+2
- ;
- ; Using the built in move routine,
- ; copy the last DIB built to the
- ; first_dib location for the next
- ; dib to be built.
- ;
- pushlong <last_dib
- pushlong <first_dib
- pushlong #dib_size
- pushword #move_sinc_dinc
-
- jsl move_info ;Move the data
- ;
- ; Restore the handle to it's
- ; origonal location. This will
- ; then be copied to every other
- ; dib that is built in this
- ; memory segment.
- ;
- ldy #dib.handle
- lda |curr_hndl
- sta [first_dib],y
- ldy #dib.handle+2
- lda |curr_hndl+2
- sta [first_dib],y
- ;
- ; Set 'next_dib' pointer to the
- ; first dib in this memory
- ; segment.
- ;
- lda <first_dib
- sta <next_dib
- lda <first_dib+2
- sta <next_dib+2
-
- ldy #dib.dvcflag
- lda [first_dib],y
- ora #cold_dib ;New DIB. Do Cold Start.
- sta [first_dib],y
- ;
- ; Reinitialise mem_dib_cnt to zero.
- ;
- lda #null
- ldy #dib.mem_dib_cnt
- sta [first_dib],y
- ;
- ; Reinitialise DIB Dev Number also.
- ;
- ldy #dib.devnum
- sta [first_dib],y
- ;
- ; Finalise the new DIB Structure?
- ;
- plp
- bcc set_link_ptrs
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'dibicise_new_dib'
- ;
- ; This routine takes the DIB located at [last_dib] and
- ; copies it into the new ram space.
- ;
- ; Inputs: <last_dib = Last DIB built (LONG)
- ; <next_dib = Next DIB start (LONG)
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: <last_dib = unchanged (LONG)
- ; <next_dib = unchanged (LONG)
- ; [last_dib] = points to this DIB (LONG)
- ; [next_dib] = defaults set (PTR)
- ; 'Int Pntrs' = Set to this DIB (LONG)s
- ; 'dispname' = Device Name (STR)
- ; |tot_dib_cnt= # of valid DIBs (WORD)
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT dibicise_new_dib
- dibicise_new_dib PROC
- ;
- ; Using the built in move routine,
- ; copy the last DIB built to the
- ; next_dib location for the next
- ; dib to be built.
- ;
- pushlong <last_dib
- pushlong <next_dib
- pushlong #dib_size
- pushword #move_sinc_dinc
-
- jsl move_info ;Move the data
-
- ;
- ; Finalise the new DIB Structure.
- ;
- EXPORT set_link_ptrs
- ;
- ; Update Links and DIB ext ptrs
- ;
- set_link_ptrs bit |rebuild
- bmi @rebuild_links
-
- clc ;we are going to add
- lda <next_dib ;get low word of this dib
- sta [last_dib] ;store in last dib (implied y = 0)
-
- adc #dib.start_blk ;adc offset to ext dib ptr
- ldy #dib.ext_ptr ;get offset to where this goes
- sta [next_dib],y ;and store low word of ptr
-
- ldy #dib.linkptr+2 ;get offset to high word
- lda <next_dib+2 ;get the high word and
- sta [last_dib],y ;store it in the last dib
-
- adc #^dib.start_blk ;adc high offset to ext ptr
- ldy #dib.ext_ptr+2 ;get offset to where this goes
- sta [next_dib],y ;and store the high word ptr
- ;
- ; Zero out the Link for this DIB
- ;
- lda #null
- ldy #dib.linkptr
- sta [next_dib],y
- ldy #dib.linkptr+2
- sta [next_dib],y
- ;
- ; Zero out the Starting Block for this DIB
- ;
- @rebuild_links lda #null
- ldy #dib.start_blk
- sta [next_dib],y
- ldy #dib.start_blk+2
- sta [next_dib],y
- ;
- ; Increment the number of active DIBs in
- ; this memory segement.
- ;
- ldy #dib.mem_dib_cnt
- lda [first_dib],y
- inc a
- sta [first_dib],y
- ;
- ; In the DIB Extension as defined for this
- ; driver is the root structure of the
- ; pointers that are used to call the SCSI
- ; Manager. At this time we need to update
- ; them so that they too point into this
- ; dib and not the last one.
- ;
- clc
- lda <next_dib ;Low word of Completion Pointer
- adc #dib.complet
- ldy #dib.compvec
- sta [next_dib],y
-
- lda <next_dib+2 ;High word of Completion Pointer
- adc #^dib.complet
- ldy #dib.compvec+2
- sta [next_dib],y
-
- clc
- lda <next_dib ;Low word of Command Packet Pointer
- adc #dib.scsicmd
- ldy #dib.cp_ptr
- sta [next_dib],y
-
- lda <next_dib+2 ;High word of Command Packet Pointer
- adc #^dib.scsicmd
- ldy #dib.cp_ptr+2
- sta [next_dib],y
-
- clc
- lda <next_dib ;Low word of Send Structure Pointer
- adc #dib.trx_buff
- ldy #dib.trx_ptr
- sta [next_dib],y
-
- lda <next_dib+2 ;High word of Send Structure Pointer
- adc #^dib.trx_buff
- ldy #dib.trx_ptr+2
- sta [next_dib],y
- ;
- ; Were we called from the
- ; main outside loop?
- ;
- lda |main_caller
- bne @skip_links ; No. Do device links.
- ;
- ; Zero out the HEAD LINK and FORWARD LINK
- ; pointers.
- ;
- ldy #dib.headlnk
- sta [next_dib],y ;Acc = 0. See Load.
- ldy #dib.fdvclnk
- sta [next_dib],y
- ldy #dib.headptr
- sta [next_dib],y ;Acc = 0. See Load.
- ldy #dib.fdvcptr
- sta [next_dib],y
- ldy #dib.headptr+2
- sta [next_dib],y ;Acc = 0. See Load.
- ldy #dib.fdvcptr+2
- sta [next_dib],y
- ;
- ; Set slot and device words in dib
- ;
- lda [dvc_list]
-
- ldy #dib.slotnum
- sta [next_dib],y
-
- ldy #$0002
- lda [dvc_list],y
-
- ldy #dib.unitnum
- sta [next_dib],y
- ;
- ; Set pointer to the descriptive or
- ; device name so that we can rev the
- ; name to prevent duplicates.
- ;
- @skip_links clc
- lda <next_dib
- adc #dib.namelen
- sta <scsi_zp0
- lda <next_dib+2
- adc #^dib.namelen
- sta <scsi_zp0+2
- ;
- ; Was internal or externally called?
- ; If internal, then we need to update
- ; the major revision part of the
- ; descriptive name. If it was external,
- ; then we will update the minor revision
- ; part only.
- ;
- lda |main_caller
- beq @do_major
- ;
- ; Do the minor revision.
- ;
- jsr minor_update
- bra @clear_busy
- ;
- ; Do the major revision.
- ;
- @do_major jsr major_update
- ;
- ; Clear artifacts. We copied this data
- ; from the first dib that has the
- ; call_active bit set. Clear the sucker.
- ;
- @clear_busy ldy #dib.dvcchar
- lda [next_dib],y
- and #call_active--\
- $ffff
- sta [next_dib],y
- ;
- ; Clear the ProDOS Bit.
- ;
- ldy #dib.dvcflag
- lda [next_dib],y
- and #pdos_part--\
- $ffff
- sta [next_dib],y
- ;
- ; Inc the DIB Count at this point.
- ; Every DIB that is succesfully built
- ; will be modified by the above code.
- ;
- stz |main_caller
- inc |tot_dib_cnt
- clc
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; MAJOR_UPDATE
- ;
- ; This routine updates the major revision portion of
- ; the descriptive name portion of the DIB.
- ;
- ; Inputs: <DIB_PTR = DIB Location
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Better be none.
- ;
- ;*******************************************************
-
- EXPORT major_update
- major_update PROC
- ;
- ; Change name so as not to conflict
- ; with any other name already built.
- ; All names end with '00' - '99'.
- ;
- short
-
- ldx #$02 ;Don't change this value.
- sec
- lda [scsi_zp0]
- ;
- ; Reset Minor Revision to '00'.
- ;
- pha
- tay
- lda #'0'
- sta [scsi_zp0],y
- dey
- sta [scsi_zp0],y
- pla
-
- sbc #$03
- tay
- @name_loop lda [scsi_zp0],y
- inc a
- cmp #'9'+1
- blt @update
- lda #'0'
- dex
- @update sta [scsi_zp0],y
- dey
- dex
- beq @name_loop
-
- longmx
-
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; MINOR_UPDATE
- ;
- ; This routine updates the minor revision portion of
- ; the descriptive name portion of the DIB.
- ;
- ; Inputs: <DIB_PTR = DIB Location
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Better be none.
- ;
- ;*******************************************************
-
- EXPORT minor_update
- minor_update PROC
- ;
- ; Change name so as not to conflict
- ; with any other name already built.
- ; All names end with '00' - '99'.
- ;
- short
-
- ldx #$02 ;Don't change this value.
- lda [scsi_zp0]
- ;
- ; Check the length of the string. If
- ; it is different from the one in the
- ; Default DIB, then we need to assume
- ; that it has been renamed. In this
- ; case, we will crank the count up by
- ; 2 but not past the max count of 31
- ; and append the version number
- ; change to that.
- ;
- cmp |default_dib+\
- dib.namelen
- beq @len_ok
- ;
- ; Has it already been adjusted?
- ;
- tay
- lda [scsi_zp0],y
- cmp #'0'
- blt @fix_it
- cmp #'9'+1
- bge @fix_it
- dey
- lda [scsi_zp0],y
- cmp #'0'
- blt @fix_it
- cmp #'9'+1
- bge @fix_it
- iny
- bra @name_loop
-
- @fix_it lda [scsi_zp0]
- inc a
- inc a
- cmp #$31
- blt @set_new_len
-
- lda #$31
- @set_new_len sta [scsi_zp0]
-
- @len_ok tay
- @name_loop lda [scsi_zp0],y
- inc a
-
- cmp #'1'
- blt @force_zero
-
- cmp #'9'+1
- blt @update
-
- @force_zero lda #'0'
- dex
- @update sta [scsi_zp0],y
- dey
- dex
- beq @name_loop
-
- longmx
-
- rts
-
- ENDP
-
- EJECT
-
- ;____DIB_Support_____
- ;*******************************************************
- ;
- ; This call is used to determine if the current DIB is
- ; the first device. This routine will return true
- ; (with the carry clear) if the device is unlinked or,
- ; if linked, then it will return true if this is the
- ; head device.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit is not the first
- ; device or it's equivelent.
- ;
- ;*******************************************************
-
- EXPORT chk_first_dvc
- chk_first_dvc PROC
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;
- ; Check Linkes to see if single device.
- ;
- ldy #dib.headlnk
- lda [dib_ptr],y
- bne @check_devnum
- ;
- ; Head Link = 0. Return True.
- ;
- @true clc
- rts
- ;
- ; Check to see if the Device Number and
- ; Head Links are the same. If not then
- ; we return false (carry set).
- ;
- @check_devnum ldy #dib.devnum
- cmp [dib_ptr],y
- beq @true
- ;
- ; Return False.
- ;
- sec
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; This call checks to see if the other device tied to
- ; it are offline. If they are then the carry will be
- ; clear on exit. If this device is tied to any other
- ; device that is currently online, then the carry will
- ; be set on exit.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit is not the only
- ; device in this link that is still
- ; online.
- ;
- ;*******************************************************
-
- EXPORT chk_lnk_offline
- chk_lnk_offline PROC
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;
- ; Get the Head Pointer. Check for null.
- ;
- clc
- ldy #dib.headptr
- lda [dib_ptr],y
- sta <scsi_zp6
- beq @over_0
- sec
- @over_0 ldy #dib.headptr+2
- lda [dib_ptr],y
- sta <scsi_zp6+2
- ;
- ; Check if ≠null.
- ;
- bne @check_it_loop
- bcs @check_it_loop
- ;
- ; It was null. This may be the head
- ; of the link. Check it out.
- ;
- ldy #dib.fdvcptr
- lda [dib_ptr],y
- ldy #dib.fdvcptr+2
- ora [dib_ptr],y
- beq @no_link ;No. Return to the caller with the carry clear.
- ;
- ; Yes. This was the head of the link.
- ; Set our pointer to this DIB.
- ;
- lda <dib_ptr
- sta <scsi_zp6
- lda <dib_ptr+2
- sta <scsi_zp6+2
- ;
- ; At this point, 'scsi_zp6' points to the
- ; head of the link. Now walk the links
- ; checking for online. If a device is
- ; online we will need to check if it is the
- ; callers device. if so, then we will
- ; continue the search. If not, we will then
- ; exit with the carry set.
- ;
- @check_it_loop ldy #dib.dvcflag
-
- lda [scsi_zp6],y
- and #dvc_online ;Is it online?
- beq @not_online ;No.
-
- lda [scsi_zp6],y ;Yes. Maybe. Check hard offline
- and #dvc_hardofl ;Is it hard offline?
- bne @not_online ;Yes.
-
- lda <scsi_zp6+2 ;Is it the caller device?
- cmp <dib_ptr+2
- bne @linked ;No.
- lda <scsi_zp6
- cmp <dib_ptr
- bne @linked ;No.
- ;
- ; Point to next device.
- ;
- @not_online clc
- ldy #dib.fdvcptr
- lda [scsi_zp6],y
- tax
- beq @over_2
- sec
- @over_2 ldy #dib.fdvcptr+2
- lda [scsi_zp6],y
- bne @save_it
- bcc @no_link
- @save_it sta <scsi_zp6+2
- stx <scsi_zp6
-
- bra @check_it_loop
-
- ;
- ; Only device online.
- ;
- @no_link clc
- rts
- ;
- ; Not the only device online.
- ;
- @linked sec
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'wake_me_up'
- ;
- ; This call walks the DIBs, slaps them in the face and
- ; pours cold water on them. It seems that they have
- ; been sleeping while P8 was running.
- ;
- ; !!!! WAAAAAAAAKE UUUUUUUP !!!!
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT wake_me_up
- wake_me_up PROC
-
- ;-------------------------------------------------------------------------------
-
- IF warm_ss_suprt = true THEN
-
- ;
- ; Start with the first DIB after
- ; the default DIB
- ;
- lda |default_dib
- sta <first_dib
- sta <next_dib
- lda |default_dib+2
- sta <first_dib+2
- sta <next_dib+2
- ;
- ; Is he asleep?
- ;
- @check_it_loop ldy #dib.dvcflag
- lda [next_dib],y
- tax
- and #relaxing
- beq @next_dib ;No he is not asleep
- ;
- ; Yes he is! Is he also Hard
- ; Offline?
- ;
- txa
- and #dvc_hardofl
- beq @not_hardofl ;No. Wake him up all the way then.
-
- txa ;Yes. Only Clear Sleep Bit.
- and #relaxing--\ ;Don't set online.
- $ffff
- sta [next_dib],y
-
- bra @next_dib
- ;
- ; Yes he is, wake him up.
- ;
- @not_hardofl txa
- and #relaxing--\
- $ffff
- ora #dvc_online
- sta [next_dib],y
- ;
- ; Advance to the next one
- ;
- @next_dib clc
- ldy #dib.linkptr
- lda [next_dib],y
- tax
- beq @over_0
- sec
- @over_0 ldy #dib.linkptr+2
- lda [next_dib],y
- sta <next_dib+2
- stx <next_dib
- ;
- ; Check if ≠null.
- ;
- bne @check_it_loop
- bcs @check_it_loop
- ;
- ; That was the last one.
- ;
- ; By default of the branches above,
- ; the Acc. = 0 and the carry is clear.
- ;
- rts
-
- ;-------------------------------------------------------------------------------
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'fix_unit_1'
- ;
- ; This call walks the DIBs, ensuring that unit 1 is
- ; the first ProDOS Partition on the disk..
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT fix_unit_1
- fix_unit_1 PROC
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;
- ; Check the pdos Bit for the Unit number 1.
- ; This may or may not be the head device.
- ;
- ldy #dib.headptr
- lda [dib_ptr],y
- sta <scsi_zp0
- ldy #dib.headptr+2
- lda [dib_ptr],y
- sta <scsi_zp0+2
- ora <scsi_zp0 ;Are we at the Head Now?
- bne @check_it ;No.
- ;
- ; We were already at the head. Set pointer
- ; to this DIB before going on.
- ;
- lda <dib_ptr
- sta <scsi_zp0
- lda <dib_ptr+2
- sta <scsi_zp0+2
- ;
- ; Is this unit number 1?
- ;
- @check_it ldy #dib.unitnum
- lda [scsi_zp0],y
- and #max_p_mask
- beq @unit_1 ;Yes.
- ;
- ; No. It's not unit number one. Check the
- ; next DIB in the link if it is non-zero.
- ;
- clc
- ldy #dib.fdvcptr
- lda [scsi_zp0],y
- tax
-
- beq @over_sec
- sec
-
- @over_sec ldy #dib.fdvcptr+2
- lda [scsi_zp0],y
-
- bne @set_ptr
- bcc @out
-
- @set_ptr sta <scsi_zp0+2
- stx <scsi_zp0
- bra @check_it
- ;
- ; This is unit 1. Is it a ProDOS Partition?
- ;
- @unit_1 ldy #dib.dvcflag
- lda [scsi_zp0],y
- and #pdos_part
- bne @out ;It's ProDOS, Get out of here.
- ;
- ; We're out of here.
- ;
- @out clc
- rts
-
- ;-------------------------------------------------------------------------------
-
- ELSE ;part_suprt = true
-
- ;-------------------------------------------------------------------------------
-
- clc
- rts
-
- ENDIF ;part_suprt = true
-
- ;-------------------------------------------------------------------------------
-
-
- ENDP ;fix_unit_1
-
- EJECT
-
- ;*******************************************************
- ;
- ; ADD_DIB_PTR
- ;
- ; This routine adds a pointer to a list of dibs to be
- ; installed by the 'POST_DRIVER_INSTALL' System
- ; Service call. Refer to the System Service ERS for
- ; details of how this works.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = High word of dib ptr
- ; X register = Low word of dib ptr
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: <DIB_PTR = Empty DIB if found
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT add_dib_ptr
- add_dib_ptr PROC
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;
- ; Check to see if this has an overide
- ; placed on it.
- ;
- lda |dpi_overide
- bmi @exit ;Yes.
- ;
- ; Is this the first time that this has been
- ; called for this session. Only the
- ; do_post_install can clear this flag.
- ;
- lda |new_list
- beq @start_over ; Acc. = 0
- ;
- ; Inc the count of new devices to be started.
- ;
- lda |new_dib_cnt
- @start_over pha
- inc a
- sta |new_dib_cnt
- sta |new_list
- pla
- ;
- ; Calculate offset for next ptr.
- ;
- asl a
- asl a
- pha
- txa
- plx
- sta |new_dib_list,x ;Place Ptr in list
- sta <scsi_zp0 ;and on zero page.
-
- tya
- sta |new_dib_list+2,x ;Place Ptr in list
- sta <scsi_zp0+2 ;and on zero page.
-
- ldy #dib.dvcflag
- lda [scsi_zp0],y
- ora #cold_dib ;New DIB. Do Cold Start.
- sta [scsi_zp0],y
-
- @exit clc
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; DO_POST_INSTALL
- ;
- ; This routine calls the 'POST_DRIVER_INSTALL' System
- ; Service call. Refer to the System Service ERS for
- ; details of how this works.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = High word of dib ptr
- ; X register = Low word of dib ptr
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: <DIB_PTR = Empty DIB if found
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT do_post_install
- do_post_install PROC
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;
- ; Check to see if this has an overide
- ; placed on it.
- ;
- lda |dpi_overide
- bmi @exit ;Yes.
- ;
- ; Clear flag indicating that the call was
- ; sent.
- ;
- stz |pdi_flag
- stz |new_list
- ;
- ; Check the count of new devices to be
- ; started.
- ;
- lda |new_dib_cnt
- beq @exit
- ;
- ; Make the call
- ;
- lda |gsos_dpage
- tcd
- ldx #new_dib_cnt
- ldy #^new_dib_cnt
-
- jsl install_driver
- pha
- lda |direct_page
- tcd
- pla
-
- bcs @exit
- dec |pdi_flag
-
- @exit clc
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;____Part_Support____
-
- ;-------------------------------------------------------------------------------
-
- IF part_suprt = true THEN
-
- ;*******************************************************
- ;
- ; READ_PM_BLK
- ;
- ;
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if operation could not be
- ; completed. Out of memory for example.
- ;
- ;*******************************************************
-
- EXPORT read_pm_blk
- read_pm_blk PROC
- ;
- ; Tell the Main Driver where
- ; our command structure resides.
- ;
- lda #@read_part
- sta <scsi_mdrvr
- lda #^@read_part
- sta <scsi_mdrvr+2
- ;
- ; And our buffer
- ;
- lda #internal_buff
- sta <buff_ptr
- lda #^internal_buff
- sta <buff_ptr+2
- ;
- ; Was this from the STARTUP Call?
- ;
- bit |rebuild
- bmi @over ;No.
- ;
- ; Yes, then stuff the pointer to
- ; the dib that we are building into
- ; the Direct Page locations. The
- ; main driver will use this to build
- ; the SCSI READ BLOCK Command that
- ; we will issue.
- ;
- lda <next_dib
- sta <dib_ptr
- lda <next_dib+2
- sta <dib_ptr+2
- ;
- ; And our length from the DIB's
- ; Block Size value
- ;
- @over lda #block_size
- sta <rqst_cnt
- lda #^block_size
- sta <rqst_cnt+2
- ;
- ; Set block to read for the next
- ; partition map block. This field
- ; is initialized to zero. Because
- ; the first partition map block is
- ; on block 1, this will be initialized
- ; to zero and then blindly incremented
- ; until we are finished.
- ;
- ; *** This is High --> Low format ***
- ;
- lda |pm_blk_num
- xba
- inc a
- xba
- sta |pm_blk_num
- ;
- ; Set internal command flag
- ;
- dec |internal
- ;
- ; Set the Partition call flag
- ;
- dec |f_partition
- ;
- ; Set the Call Type and Issue the
- ; READ BLOCK Command.
- ;
- lda #scsit_stat
- sta |call_type
- ;
- ; Issue the call.
- ;
- jsr check_532_rw
-
- @rts rts
- ;
- ; Data for the READ BLOCK Command
- ;
- @read_part dc.b $08
- dc.b null
- EXPORT pm_blk_num
- pm_blk_num dc.w null
- dcb.b 10,null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; CHK_MAP
- ;
- ; This routine checks the validity of the partition
- ; map block currently loaded in the internal buffer.
- ; This need only be called once per device. If the
- ; map is valid, then the carry will be clear. The 'Z'
- ; flag will also be set if this is not the first time
- ; that this routine was called for this device. If
- ; the carry is set, then the map was invalid and the
- ; block count at 'T_DVC_BLOCKS' has been placed in the
- ; DIB pointed to by 'DIB_PTR'. The starting block will
- ; also have been set to null.
- ;
- ; Inputs: <DIB_PTR = DIB Location
- ; |T_DVC_BLOCKS = Total blocks for this device
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; = Z = 0 if routine called before
- ; = C = 1 if not a partition map
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if 'internal_buff does not
- ; contain a valid Partition map entry.
- ;
- ;*******************************************************
-
- EXPORT chk_map
- chk_map PROC
- ;
- ; Valid Partition Map?
- ;
- @over_0 inc |first_time ;Don't need to do this but once.
- bne @clc ;Already done if taken.
-
- lda |pm.Sig\
- +internal_buff
- cmp #Part_sig
- bne no_partition ;No.
-
- @clc clc
- rts
- ;
- ; We didn't have a valid partition
- ; map, so this device will be
- ; treated as a single non-partitioned
- ; device.
- ;
- EXPORT no_partition
-
- no_partition ldy #dib.blkcnt
- lda |t_dvc_blocks
- sta [dib_ptr],y
- ldy #dib.blkcnt+2
- lda |t_dvc_blocks+2
- sta [dib_ptr],y
- ldy #dib.start_blk
- lda #null
- sta [dib_ptr],y
- ldy #dib.start_blk+2
- sta [dib_ptr],y
- ;
- ; Mark DIB as online and switched.
- ;
- ldy #dib.dvcflag
- lda [dib_ptr],y
- and #dvc_hardofl--\
- $ffff
- ora #dvc_switch++\
- dvc_online
- sta [dib_ptr],y
-
- sec
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'check_map_entry'
- ;
- ; Check the Partition Map Entry currently loaded in
- ; the internal buffer. If it is of type
- ; 'Apple_partition_map', 'Apple_Free', or
- ; 'Apple_Scratch', then this routine will return with
- ; the carry set. Any other type will return with the
- ; carry clear. In addition, 'Apple_ProDOS' will
- ; return with the overflow flag set.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Partition Map Entry is not
- ; for a valid Volume. Overflow set if the
- ; Partition is a ProDOS Partition.
- ;
- ;*******************************************************
-
- EXPORT check_map_entry
- check_map_entry PROC
- ;
- ; This routine runs in
- ; 8 bit m and x only.
- ;
- short
- ;
- ; Is it ProDOS?
- ;
- ldx #@p_map-@prodos-2
- ldy #null
-
- @loop lda |pm.PartType\
- +internal_buff,y
- beq @over_0 ;Yes or null. Either way we do the rest.
- cmp @prodos,y
- beq @next
- eor #'A'--'a'
- cmp @prodos,y
- bne @over_0 ;No. Continue on.
- @next iny
- dex
- bpl @loop
- brl @pdos_part ;Skip over 8 bit code area to 16 bit area.
- ;
- ; Is it the Partition Map?
- ;
- @over_0 ldx #32-1
- ldy #null
-
- @loop_0 lda |pm.PartType\
- +internal_buff,y
- beq @skip ;Yes or null. Either way we skip it.
- cmp @p_map,y
- beq @next_0
- eor #'A'--'a'
- cmp @p_map,y
- bne @over_1 ;No. Continue on.
- @next_0 iny
- dex
- bpl @loop_0
- bra @skip ;Yes. Skip it.
- ;
- ; Is it a FREE Partition?
- ;
- @over_1 ldx #32-1
- ldy #null
-
- @loop_1 lda |pm.PartType\
- +internal_buff,y
- beq @skip ;Yes or null. Either way we skip it.
- cmp @free,y
- beq @next_1
- eor #'A'--'a'
- cmp @free,y
- bne @over_2 ;No. Continue on.
- @next_1 iny
- dex
- bpl @loop_1
- bra @skip ;Yes. Skip it.
- ;
- ; Is it a SCRATCH Partition?
- ;
- @over_2 ldx #32-1
- ldy #null
-
- @loop_2 lda |pm.PartType\
- +internal_buff,y
- beq @skip ;Yes or null. Either way we skip it.
- cmp @scratch,y
- beq @next_2
- eor #'A'--'a'
- cmp @scratch,y
- bne @over_3 ;No. Continue on.
- @next_2 iny
- dex
- bpl @loop_2
- ;
- ; At this point the Current Partition
- ; Type matched one of the three types
- ; checked for. Exit with the carry
- ; set.
- ;
- @skip longmx
- sec
- rts
- ;
- ; At this point the Current Partition
- ; Type did not match one of the three
- ; types checked for and it was not a
- ; ProDOS Partition.. Exit with the
- ; Carry and Overflow bits clear.
- ;
- @over_3 longmx
- clc
- clv
- rts
- ;
- ; At this point the Current Partition
- ; Type is a ProDOS Partition. Exit with
- ; the Carry clear and Overflow set.
- ;
- @pdos_part longmx
- clc
- sep #%01000000 ;Set the v flag
- rts
- ;
- ; Inactive Partion Types to check for.
- ;
- STRING ASIS
-
- @prodos dc.b 'Apple_ProDOS'
- dc.b $00
- @p_map dc.b 'Apple_partition_map'
- dc.b $00
- @free dc.b 'Apple_Free'
- dc.b $00
- @scratch dc.b 'Apple_Scratch'
- dc.b $00
-
- STRING PASCAL
-
- ENDP
-
- EJECT
-
- ELSE ;part_suprt = true
-
- ;-------------------------------------------------------------------------------
-
- EXPORT read_pm_blk
- read_pm_blk PROC
-
- EXPORT check_map_entry
- check_map_entry
- lda #null
- clc
- clv
- rts
-
-
- EXPORT pm_blk_num
- pm_blk_num dc.w null
-
- EXPORT chk_map
- chk_map
- ;
- ; We can't have a valid partition
- ; map, so this device will be
- ; treated as a single non-partitioned
- ; device.
- ;
- EXPORT no_partition
-
- no_partition ldy #dib.blkcnt
- lda |t_dvc_blocks
- sta [dib_ptr],y
- ldy #dib.blkcnt+2
- lda |t_dvc_blocks+2
- sta [dib_ptr],y
- ldy #dib.start_blk
- lda #null
- sta [dib_ptr],y
- ldy #dib.start_blk+2
- sta [dib_ptr],y
- ;
- ; Mark DIB as online and switched.
- ;
- ldy #dib.dvcflag
- lda [dib_ptr],y
- and #dvc_hardofl--\
- $ffff
- ora #dvc_switch++\
- dvc_online
- sta [dib_ptr],y
-
- sec
- rts
-
- ENDIF ;part_suprt = true
-
- ;-------------------------------------------------------------------------------
-
- ;____Cache_Suport____
-
- ;-------------------------------------------------------------------------------
-
- IF cache_blks = true THEN
-
- ;*******************************************************
- ;
- ; 'r_all_in_cache'
- ;
- ; This routine is used to check if the entire
- ; requested block count is in the cache. This routine
- ; will check each block individually, incrementing the
- ; block count and subtracting the block size from the
- ; request count until either a block is found that is
- ; not in the cache (Exit Carry Set) or request count
- ; has been exausted (Exit Carry Clear).
- ;
- ; On entry this routine clears some values to indicate
- ; it's starting point for this call. As it goes
- ; throughthe cache looking for blocks, it will fetch
- ; the block from the cache and advance the starting
- ; point. What this does is eliminate double searches
- ; throughthe cache and if a read is needed, these
- ; blocks will not have to be transfered. When this
- ; routine exits, the caller will think that the first
- ; block that we found that was not in the cache was
- ; the first block requested. For this reason, any
- ; code that uses this call will need to preserve those
- ; values so that they can be restored on exit.
- ;
- ; If we receive a Read Call for 256 blocks and the
- ; first 128 are in the cache, then we don't want to
- ; re-read them, and we don't want to do a find again
- ; later when we fetch them. let's fetch them now and
- ; advance our pointers.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; <buff_ptr = Original Starting Buffer
- ; <rqst_cnt = Original Request Count
- ; <block_num = Original Starting Block
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; <buff_ptr = New Starting Buffer
- ; <rqst_cnt = New Request Count
- ; <block_num = New Starting Block
- ; Data Bank = Ours
- ;
- ; Errors: Acc = 0 and Carry set if 1 or more
- ; blocks of the request are not in the
- ; cache.
- ;
- ; Acc <> 0 if any other error occurs.
- ; Error code is in Acc.
- ;
- ;*******************************************************
-
- EXPORT r_all_in_cache
- r_all_in_cache PROC
- ;
- ; Switch Direct Pages.
- ;
- lda |gsos_dpage
- tcd
- ;
- ; Get the requested count and devide
- ; by block size to get the loop counter.
- ; If Count = 0, then exit.
- ;
- lda <rqst_cnt
- sta |divend
- lda <rqst_cnt+2
- sta |divend+2
-
- ora <rqst_cnt
- bne @continue
-
- lda |direct_page
- tcd
- lda #null
- clc
- @rts rts
-
- ;
- ; Call divide routine.
- ;
- @continue lda <blk_size
- sta |divsor
-
- jsr divide
- bcc @over_divide
-
- lda |direct_page
- tcd
-
- lda #drvr_bad_cnt ;non-integral rqst count.
- sec
- rts
- ;
- ; Count = count -1. This way we can
- ; use a BMI to exit with.
- ;
- @over_divide lda |result+2
- sta @blk_cnt+2
- lda |result
- sta @blk_cnt
- bne @over_dec_high
- dec @blk_cnt+2
- @over_dec_high dec @blk_cnt
- ;
- ; Setup is now completed. Now we start to
- ; check to see if the blocks are in the
- ; cache.
- ;
- @chk_blk_loop sec ;return error if not in cache. Don't add.
- jsr |get_from_cache
- bcc @found
- lda #null ;Not there. Clear the Acc. and Exit.
- bra @restore
- ;
- ; Are there any more to do?
- ;
- @found lda @blk_cnt
- bne @over_dec
- dec @blk_cnt+2
- bpl @over_dec
- ;
- ; No. Count is exausted.
- ;
- lda #null
- clc
- bra @restore
- ;
- ; Yes. Finish the DEC and update the
- ; Buffer Pointer, Request Count, and
- ; the Block Number.
- ;
- @over_dec dec @blk_cnt
-
- clc ;Bump Buffer Pointer
- lda <buff_ptr
- adc <blk_size
- sta <buff_ptr
- lda <buff_ptr+2
- adc #null
- sta <buff_ptr+2
-
- sec ;Back off Request Count
- lda <rqst_cnt
- sbc <blk_size
- sta <rqst_cnt
- lda <rqst_cnt+2
- sbc #null
- sta <rqst_cnt+2
-
- inc <block_num ;Inc the Block Number
- bne @chk_blk_loop
- inc <block_num+2
- bra @chk_blk_loop
- ;
- ; We are finished. We don't need to
- ; know if we were succesfull. We only
- ; need to restore the state of the
- ; corrupted direct page values while
- ; preserving the Acc. and Carry bit.
- ;
- @restore pha
- php
-
- ldx |direct_page
-
- lda <buff_ptr
- sta >buff_ptr,x
- sta |c_strt_buffer
- lda <buff_ptr+2
- sta >buff_ptr+2,x
- sta |c_strt_buffer+2
-
- lda <rqst_cnt
- sta >rqst_cnt,x
- sta |c_strt_rqst_cnt
- lda <rqst_cnt+2
- sta >rqst_cnt+2,x
- sta |c_strt_rqst_cnt+2
-
- lda <block_num
- sta >block_num,x
- sta |c_strt_blk_num
- lda <block_num+2
- sta >block_num+2,x
- sta |c_strt_blk_num+2
- ;
- ; Validate Flag for the Read Cache
- ; Routines
- ;
- dec |cache_valid
-
- txa
- tcd
-
- plp
- pla
- rts
- ;
- ; Internal Data
- ;
- @blk_cnt dc.l null
- ;
- ; The following values are used to advance
- ; the starting point of the cache calls.
- ;
- EXPORT c_strt_buffer
- EXPORT c_strt_rqst_cnt
- EXPORT c_strt_blk_num
- EXPORT cache_valid
-
- c_strt_buffer dc.l null ;Starting Buffer Pointer
- c_strt_rqst_cnt dc.l null ;Starting Request Count
- c_strt_blk_num dc.l null ;Starting Block Number
- cache_valid dc.w null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'w_update_cache'
- ;
- ; This routine is used when writting data to the disk
- ; with a cache priority of $0000. If the block is in
- ; the cache, then the cache will be updated. If not,
- ; then nothing will happen.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ; Carry Clear = Always place in cache
- ; Carry set = Only place in cache if
- ; already there.
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if requested block is not
- ; added to the cache.
- ;
- ;*******************************************************
-
- EXPORT w_update_cache
- w_update_cache PROC
- ;
- ; Zero Deferred Write failed flag.
- ;
- stz @deferred
- ;
- ; Preserve Carry Flag for later.
- ;
- php
- ;
- ; Set GS/OS Direct Page
- ;
- lda |gsos_dpage
- tcd
- ;
- ; Preserve Block Number and request
- ; count. Set count to 1 block per
- ; call.
- ;
- lda <buff_ptr
- sta @orig_buff
-
- lda <rqst_cnt
- sta @bytes_rem
-
- lda <block_num
- sta @start_blk
-
- lda <buff_ptr+2
- sta @orig_buff+2
-
- lda <rqst_cnt+2
- sta @bytes_rem+2
-
- lda <block_num+2
- sta @start_blk+2
- ;
- ; Is the requested block in the cache?
- ;
- @do_cache plp
- php
- jsr put_in_cache
- bcc @cached ;Carry set only if a deferred write
- dec @deferred ;failed to go in the cache.
- ;
- ; Advance to the next block.
- ;
- @cached inc <block_num
- bne @over
- inc <block_num+2
- ;
- ; Bump Buffer Pointer.
- ;
- @over clc
- lda <buff_ptr
- adc <blk_size
- sta <buff_ptr
- bcc @over_1
- inc <buff_ptr+2
- ;
- ; Any Data Left
- ;
- @over_1 sec
- lda @bytes_rem
- sbc <blk_size
- sta @bytes_rem
- sta |temp_acc
-
- lda @bytes_rem+2
- sbc #null
- sta @bytes_rem+2
- ora |temp_acc
-
- bne @do_cache ;Yes.
- clc
- ;
- ; Restore Values.
- ;
-
- @restore lda @orig_buff
- sta <buff_ptr
-
- lda @start_blk
- sta <block_num
-
- lda @orig_buff+2
- sta <buff_ptr+2
-
- lda @start_blk+2
- sta <block_num+2
- ;
- ; Exit.
- ;
- lda |direct_page
- tcd
-
- lda @deferred
- beq @clean_out
- plp ;Restore the Stack.
- sec
- rts
-
- @clean_out plp ;Restore the Stack.
- clc
- rts
- ;
- ; Internal Data
- ;
- @deferred dc.w null
- @orig_buff dc.l null
- @bytes_rem dc.l null
- @start_blk dc.l null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'put_in_cache'
- ;
- ; This routine is used to place the current block in
- ; the cache. First we will check if the requested
- ; block is in the cache. If the block is not in the
- ; cache then we will add it. if there is no room and
- ; the driver call was issued in deferred mode then we
- ; will exit with the carry set. In all other cases
- ; we will exit Carry Clear.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ; Carry Clear = Always place in cache
- ; Carry set = Only place in cache if
- ; already there.
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if requested block is not
- ; added to the cache in deferred mode
- ; only.
- ;
- ;*******************************************************
-
- EXPORT put_in_cache
- put_in_cache PROC
- ;
- ; Is the requested block in the cache?
- ;
- php
-
- clc
- jsl cache_find_blk
-
- bcc @move_it_in ;Yes. It is.
- plp
- bcs @clc
- ;
- ; Not there. Allocate space.
- ;
- jsl cache_add_blk
- bcc @skip_fix
- lda <cache_prio ;Deferred Mode?
- bpl @clc ;No. Exit Carry Clear.
- rts ;Yes. Exit carry set
- ;
- ; Move the block in.
- ;
- @move_it_in plp ;Restore the stack.
-
- @skip_fix pei <buff_ptr+2
- pei <buff_ptr
- pei <cache_ptr+2
- pei <cache_ptr
- pea $0000
- pei <blk_size
- pea |move_sinc_dinc
- jsl move_info
- ;
- ; Exit.
- ;
- @clc clc
- @rts rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'r_get_cache'
- ;
- ; This routine is used when reading data from the disk
- ; with a cache priority of $0000. If the block is in
- ; the cache, then the data will be updated. If not,
- ; then nothing will happen.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ; Carry Clear = Always place in cache
- ; Carry set = Only place in cache if
- ; already there.
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if requested block is not
- ; added to the cache.
- ;
- ;*******************************************************
-
- EXPORT r_get_cache
- r_get_cache PROC
- ;
- ; Preserve Carry Flag for later.
- ;
- php
- ;
- ; Check Validity of the call.
- ;
- lda |cache_valid
- bmi @valid
-
- plp
- lda #drvr_bad_code
- sec
- rts
- ;
- ; Set GS/OS Direct Page
- ;
- @valid lda |gsos_dpage
- tcd
- ;
- ; Get Request count.
- ;
- lda |c_strt_rqst_cnt
- sta @bytes_rem
- lda |c_strt_rqst_cnt+2
- sta @bytes_rem+2
- ;
- ; Is the requested block in the cache?
- ;
- @do_cache plp
- php
- jsr get_from_cache
- ;
- ; Advance to the next block.
- ;
- inc <block_num
- bne @over
- inc <block_num+2
- ;
- ; Bump Buffer Pointer.
- ;
- @over clc
- lda <buff_ptr
- adc <blk_size
- sta <buff_ptr
- bcc @over_1
- inc <buff_ptr+2
- ;
- ; Any Data Left
- ;
- @over_1 sec
- lda @bytes_rem
- sbc <blk_size
- sta @bytes_rem
- sta |temp_acc
-
- lda @bytes_rem+2
- sbc #null
- sta @bytes_rem+2
- ora |temp_acc
-
- bne @do_cache ;Yes.
- ;
- ; Exit.
- ;
- stz |cache_valid ;Cache Values no longer valid
-
- lda |direct_page
- tcd
-
- plp ;Restore the Stack.
- clc
- rts
- ;
- ; Internal Data
- ;
- @bytes_rem dc.l null
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'get_from_cache'
- ;
- ; This routine is used to get the current block from
- ; the cache. First we will check if the requested
- ; block is in the cache. If the block is not in the
- ; cache then we will exit with the Carry Set. If it
- ; is found, then we will move it to the requested ram
- ; and exit Carry Clear.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if requested block is not
- ; in the cache.
- ;
- ;*******************************************************
-
- EXPORT get_from_cache
- get_from_cache PROC
- ;
- ; Is the requested block in the cache?
- ;
- php
-
- clc
- jsl cache_find_blk
-
- bcc @move_it_in ;Yes. It is.
- plp
- bcs @rts
- ;
- ; Not there. Allocate space.
- ;
- jsl cache_add_blk
- bcs @rts
-
- pei <buff_ptr+2
- pei <buff_ptr
- pei <cache_ptr+2
- pei <cache_ptr
- pea $0000
- pei <blk_size
- pea |move_sinc_dinc
- jsl move_info
-
- bra @clc
- ;
- ; Move the block in.
- ;
- @move_it_in plp ;Restore the stack.
-
- @skip_fix pei <cache_ptr+2
- pei <cache_ptr
- pei <buff_ptr+2
- pei <buff_ptr
- pea $0000
- pei <blk_size
- pea |move_sinc_dinc
- jsl move_info
- ;
- ; Exit.
- ;
- @clc clc
- @rts rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'ko_cache'
- ;
- ; This routine is used to kill all blocks that are
- ; cached that are included in a device specific write
- ; type call.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT ko_cache
- ko_cache PROC
- ;
- ; Switch Direct Pages.
- ;
- lda |gsos_dpage
- tcd
- ;
- ; Preserve the block number on direct
- ; page.
- ;
- lda <block_num
- sta |scratch0
- lda <block_num+2
- sta |scratch1
- ;
- ; Set our starting block number on
- ; direct page.
- ;
- lda |killer_blk
- sta <block_num
- lda |killer_blk+2
- sta <block_num+2
- ;
- ; Get the requested count and devide
- ; by block size to get the loop counter.
- ; If Count = 0, then exit.
- ;
- lda <rqst_cnt+2
- sta |divend+2
- lda <rqst_cnt
- sta |divend
- ora <rqst_cnt+2
- bne @do_devide
-
- clc
- @rts bra @restore
- ;
- ; Call divide routine.
- ;
- @do_devide lda <blk_size
- sta |divsor
-
- jsr divide
- bcc @over_divide
- lda #drvr_bad_cnt ;non-integral rqst count.
- sec
- bra @restore
- ;
- ; Count = count -1. This way we can
- ; use a BMI to exit with.
- ;
- @over_divide lda |result+2
- sta @blk_cnt+2
- lda |result
- sta @blk_cnt
- bne @over_dec_high
- dec @blk_cnt+2
- @over_dec_high dec @blk_cnt
- ;
- ; Setup is now completed. Now we start to
- ; check to see if the blocks are in the
- ; cache.
- ;
- @chk_blk_loop jsl cache_kil_blk
- ;
- ; Are there any more to do?
- ;
- lda @blk_cnt
- bne @over_dec
- dec @blk_cnt+2
- bpl @over_dec
- ;
- ; No. Count is exausted.
- ;
- clc
- bra @restore
- ;
- ; Yes. Finish the DEC and update
- ; the block number.
- ;
- @over_dec dec @blk_cnt
-
- inc <block_num
- bne @chk_blk_loop
- inc <block_num+2
- bra @chk_blk_loop
- ;
- ; We are finished. We don't need to
- ; know if we were succesfull. We only
- ; need to restore the state of the
- ; corrupted direct page values while
- ; preserving the Acc. and Carry bit.
- ;
- @restore pha
- php
- lda |scratch0
- sta <block_num
- lda |scratch1
- sta <block_num+2
-
- lda |direct_page
- tcd
-
- plp
- pla
- rts
- ;
- ; Internal Data
- ;
- @blk_cnt dc.l null
-
- ENDP
-
- EJECT
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- EXPORT put_in_cache
-
- put_in_cache PROC
-
- EXPORT get_from_cache
- EXPORT c_strt_buffer
- EXPORT c_strt_rqst_cnt
- EXPORT c_strt_blk_num
- EXPORT cache_valid
-
- get_from_cache sec
- rts
-
- c_strt_buffer
- c_strt_rqst_cnt
- c_strt_blk_num
- cache_valid dc.w null
-
- ENDP
-
- EJECT
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ;____Device_Tests____
- ;*******************************************************
- ;
- ; 'unit_state'
- ;
- ; Tests the Target Device to see if it is ready to
- ; accept our commands. If the device responds with a
- ; CHECK CONDITION, then we will find out why and
- ; perform the correct actions.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ; <dib_ptr = Called DIB
- ;
- ; Outputs: Acc = Error Code if any
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ; <dib_ptr = Called DIB
- ;
- ; Errors: Carry set if Unit no ready.
- ;
- ;*******************************************************
-
- EXPORT unit_state
- unit_state PROC
- ;
- ; This device is removable. Now we
- ; need to check to see if the unit
- ; has gone offline, (then we need to
- ; report that to the OS) or if the
- ; unit has come back online (Rebuild
- ; the DIBs).
- ;
- jsr test_unit_rdy ;Is there anything that we should know about?
- bcc @ready_to_go ;No.
-
- lda |auto_sense_data+\
- rqst_sens.sense_key
- beq @ready_to_go
-
- and #$00ff
- cmp #$0006
- beq @do_switch
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
-
- lda auto_sense_data+\ ;Was it a RESET?
- rqst_sens.addnl_sens_code
- and #$00fe
- cmp #$0028 ;Checking for $28 (Medium Changed), $29 (RESET)
- bne @io_error
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = apple_cd THEN
-
- lda auto_sense_data+\ ;Was it a RESET?
- rqst_sens.addnl_sens_code
- and #$00ff
- cmp #$00b7 ;Checking for $B7 (Media being mounted)
- beq @do_switch
- cmp #$00b0 ;Checking for $B0 (NO MEDIA)
- beq @off_line
- and #$00fe
- cmp #$0028 ;Checking for $28 (Medium Changed), $29 (RESET)
- bne @io_error
- ;
- ; Set this location to a $B0. This will
- ; prevent problems if the device is reset
- ; durring startup while auto sensing is
- ; off.
- ;
- lda #$00b0
- sta auto_sense_data+\
- rqst_sens.addnl_sens_code
- bra unit_state
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ;
- ; Rebuild the DIBs.
- ;
- @do_switch jsr test_unit_rdy ;Is it ready yet?
- bcc @its_ready ;Yes.
- lda auto_sense_data+\ ;Is there media in the drive?
- rqst_sens.addnl_sens_code
- and #$00ff
- cmp #$00b0 ;Checking for $B0 (NO MEDIA)
- bne @do_switch ;No.
-
- @its_ready jsr set_512_mode
- ;
- ; Issue the READ CAPACITY Command.
- ;
- jsr read_capacity
- bcs @over_0 ;Was there an error?
- ;
- ; Get the Block Count (Stored
- ; High >> Low. Must be switched
- ; to Low >> High). This is the last
- ; readable block number. Add 1 to
- ; it for comparison reasons.
- ;
- lda |block.count\
- +internal_buff\
- +2
- xba
- adc #$0001
- sta |t_dvc_blocks
- lda |block.count\
- +internal_buff
- xba
- adc #null
- sta |t_dvc_blocks+2
-
- @over_0 stz |trash_it ;DO NOT TRASH THIS DISK.
-
- pei <dib_ptr
- pei <dib_ptr+2
-
- jsr rebld_dibs ;Rebuild DIBs and Issue a DISK_SW for each
-
- tax
- pla
- sta <dib_ptr+2
- pla
- sta <dib_ptr
- txa
-
- php
- ;
- ; Restore the original Direct Page values.
- ;
- jsr set_our_dp
- plp
- bcc @switch_error
- jsr test_unit_rdy
- bcs @io_error
- ;
- ; Disk Switched Error.
- ;
- @switch_error lda #drvr_dsk_swch
- sec
- rts
- ;
- ; Are we really ready to go? If the
- ; dvc_hard_sw flag is set, then we
- ; will clear it and report the device
- ; as switched.
- ;
- @ready_to_go ldy #dib.dvcflag
- lda [dib_ptr],y
- tax
-
- and #dvc_hard_sw
- beq @no_switch
-
- txa
- and #dvc_hard_sw--\
- $ffff
- sta [dib_ptr],y
-
- @no_switch lda #null
- clc
- @rts rts
- ;
- ; Some kind of I/O Error.
- ;
- @io_error lda #drvr_io
- sec
- rts
- ;
- ; Device is currently offline.
- ;
- @off_line lda #drvr_off_line
- sec
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'test_unit_rdy'
- ;
- ; Test the Target Device to see if it is ready to
- ; accept our commands. If the device responds with a
- ; CHECK CONDITION, then it will be up to the caller of
- ; this routine to find out why. This is not a test
- ; routine.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit no ready.
- ;
- ;*******************************************************
-
- EXPORT test_unit_rdy
- test_unit_rdy PROC
- ;
- ; Set Internal Command Flag
- ;
- dec |internal
- ;
- ; Set Parm Pointer.
- ;
- lda #@test_unit_p
- sta <scsi_mdrvr
- lda #^@test_unit_p
- sta <scsi_mdrvr+2
- ;
- ; It's a Status Call.
- ;
- lda #scsit_stat
- sta |call_type
- ;
- ; Issue the Call
- ;
- jmp |main_drvr
- ;
- ; Data for this call
- ; TEST UNIT READY Command Packet
- ;
- @test_unit_p dc.b $00 ;Command Number
- dc.b $00 ;SCSI Command Flags
- dcb.b 3,$00 ;Reserved
- dc.b $00 ;Vendor Unique
- dcb.b 6,$00 ;Resrved
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'CHK_PLAY_MODE'
- ;
- ; This command is used to tell if the device is
- ; currently in Audio Play Mode.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set not in play mode
- ;
- ;*******************************************************
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = apple_cd THEN
-
- EXPORT chk_play_mode
- chk_play_mode PROC
- ;
- ; First, disable auto sensing.
- ;
- ldy #dib.rslt_ptr
- lda [dib_ptr],y
- pha
- lda #null
- sta [dib_ptr],y
-
- ldy #dib.rslt_ptr+2
- lda [dib_ptr],y
- pha
- lda #null
- sta [dib_ptr],y
- ;
- ; Set Internal Command Flag
- ;
- dec |internal
- ;
- ; Set Parm length.
- ;
- lda #$0006
- sta <rqst_cnt
- stz <rqst_cnt+2
- ;
- ; Set Parm Pointer.
- ;
- lda #@chk_play
- sta <scsi_mdrvr
- lda #^@chk_play
- sta <scsi_mdrvr+2
- ;
- ; Set Buff Pointer.
- ;
- lda #@play_data
- sta <buff_ptr
- lda #^@play_data
- sta <buff_ptr+2
- ;
- ; It's a Status Call.
- ;
- lda #scsit_stat
- sta |call_type
- ;
- ; Issue the Call
- ;
- jsr |main_drvr
- bcs @restore_dp ;Carry is set. Not play mode
- ;
- ; Check the Status.
- ;
- ; Status $00 = In play mode
- ; $01 = Pause (Play Mode)
- ; $02 = Muting (Play Mode)
- ;
- ; $03 = Play completed (No Play)
- ; $04 = Error (No Play)
- ; $05 = Play not requested.
- ;
- lda @play_data
- and #$0007
- cmp #$0003 ; <3 = Carry Clear. =>3 = Carry set
- ;
- ; Restore the Direct Page Values.
- ;
- @restore_dp php
- jsr set_our_dp
- plp
- ;
- ; Restore Auto Sensing Pointer.
- ;
- ldy #dib.rslt_ptr+2
- pla
- sta [dib_ptr],y
-
- ldy #dib.rslt_ptr
- pla
- sta [dib_ptr],y
-
- rts
- ;
- ; AUDIO STATUS Command Packet
- ;
- @chk_play dc.b $cc ;Command Number
- dc.b null ;SCSI Command Flags
- dcb.b 10,null ;Reserved
- ;
- ; Data received for this call
- ;
- @play_data dcb.b 6,null
-
- ENDP
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- EJECT
-
- ;*******************************************************
- ;
- ; The REQUEST SENSE Call is used to request any
- ; information from the target device that might tell
- ; us something about the way that the last call
- ; competed. This call should always be issued if any
- ; SCSI Command returns from the SCSI Manager with a
- ; CHECK CONDITION in the status result field. The
- ; data returned will be kept until the next REQUEST
- ; SENSE Command is issued. A flag however will be set
- ; if any other commands are received by the SCSI Driver
- ; indicating that this data is outdated.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; |sense_data = Data returned by the device
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit no ready.
- ;
- ;*******************************************************
-
- EXPORT rqst_sense
- rqst_sense PROC
- ;
- ; Set Internal Command Flag
- ;
- dec |internal
- ;
- ; Set Parm Pointer.
- ;
- lda #@rqst_sens_p
- sta <scsi_mdrvr
- lda #^@rqst_sens_p
- sta <scsi_mdrvr+2
- ;
- ; Preserve the Current Direct
- ; Page values stored in the
- ; buff_ptr and rqst_cnt fields.
- ;
- pei <buff_ptr
- pei <buff_ptr+2
- pei <rqst_cnt
- pei <rqst_cnt+2
- ;
- ; Set our own buffer pointer
- ; for this call.
- ;
- lda #sense_data
- sta <buff_ptr
- lda #^sense_data
- sta <buff_ptr+2
- ;
- ; Set our own request count
- ; for this call.
- ;
- lda #$0010
- sta <rqst_cnt
- stz <rqst_cnt+2
- ;
- ; It's a Status Call.
- ;
- lda #scsit_stat
- sta |call_type
- ;
- ; Issue the Call
- ;
- stz @error
- jsr |main_drvr
- bcc @return_dp
- ;
- ; Save error code
- ;
- sta @error
- ;
- ; Restore the Direct Page Values.
- ;
- @return_dp pla
- sta <rqst_cnt+2
- pla
- sta <rqst_cnt
- pla
- sta <buff_ptr+2
- pla
- sta <buff_ptr
- ;
- ; Restore the Acc resutl.
- ;
- lda @error
- cmp #$0001
- rts
- ;
- ; Data for this call
- ;
- @error dc.w null
- ;
- ; REQUEST SENSE Command Packet
- ;
- @rqst_sens_p dc.b $03 ;Command Number
- dc.b $00 ;SCSI Command Flags
- dcb.b 3,$00 ;Reserved
- dc.b $00 ;Vendor Unique
- dcb.b 6,$00 ;Reserved
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'reserve_unit'
- ;
- ; The RESERVE UNIT Call is used to reserve the target
- ; device for use by this host only.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; |sense_data = Data returned by the device
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit already reserved.
- ;
- ;*******************************************************
-
- EXPORT reserve_unit
- reserve_unit PROC
-
-
- lda #null
- clc
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'release_unit'
- ;
- ; The RELEASE UNIT Call is used to release the target
- ; device from use by this host only.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; |sense_data = Data returned by the device
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT release_unit
- release_unit PROC
-
- lda #null
- clc
- rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'mode_sense'
- ;
- ; This routine issues an MODE SENSE call to the device.
- ;
- ; Inputs: <dib_ptr = DIB start (LONG)
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT mode_sense
- mode_sense PROC
- ;
- ; Initialize the Page code to 1
- ;
- lda #$0001
- sta @page_code
- ;
- ; Set internal command flag
- ;
- @try_again dec |internal
- ;
- ; Tell the Main Driver where
- ; our command structure resides.
- ;
- lda #@start_mode
- sta <scsi_mdrvr
- lda #^@start_mode
- sta <scsi_mdrvr+2
- ;
- ; And our buffer
- ;
- lda #internal_buff
- sta <buff_ptr
- lda #^internal_buff
- sta <buff_ptr+2
- ;
- ; And our length of $ff Bytes
- ;
- lda #$0014
- sta <rqst_cnt
- stz <rqst_cnt+2
- ;
- ; Set the Call Type and Issue the
- ; MODE SENSE Command.
- ;
- lda #scsit_stat
- sta |call_type
- jsr |main_drvr
- bcc @rts
- pha
- lda @page_code
- beq @pla
- pla
- stz @page_code
- bra @try_again
-
- @pla pla
- @rts rts
- ;
- ; Data for the MODE SENSE Command
- ;
- @start_mode dc.b $1a
- dc.b $00
- @page_code dc.b $01
- dcb.b 9,$00
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'read_capacity'
- ;
- ; This routine issues an READ CAPACITY call to the
- ; device and then uses the data returned to fill in
- ; some of the blank holes in the DIB.
- ;
- ; Inputs: <dib_ptr = DIB start (LONG)
- ; Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Carry = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT read_capacity
- read_capacity PROC
-
- ;-------------------------------------------------------------------------------
-
- IF block_dvc = true\
- AND character_dvc = false THEN
- ;
- ; Set internal command flag
- ;
- dec |internal
- ;
- ; Tell the Main Driver where
- ; our command structure resides.
- ;
- lda #@read_cap
- sta <scsi_mdrvr
- lda #^@read_cap
- sta <scsi_mdrvr+2
- ;
- ; And our buffer
- ;
- lda #internal_buff
- sta <buff_ptr
- lda #^internal_buff
- sta <buff_ptr+2
- ;
- ; And our length of $ff Bytes
- ;
- lda #$0008
- sta <rqst_cnt
- stz <rqst_cnt+2
- ; Set the Call Type and Issue the
- ; READ CAPACITY Command.
- ;
- lda #scsit_stat
- sta |call_type
- jsr |main_drvr
- rts
- ;
- ; Data for the READ CAPACITY Command
- ;
- @read_cap dc.b $25
- dcb.b 11,$00
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'get_data_status'
- ;
- ; The GET DATA STATUS Call is used to find out how
- ; much data is available to be read from the Scanner.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; |sense_data = Data returned by the device
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT get_data_status
- get_data_status PROC
-
-
- lda #null
- clc
- rts
-
- ENDP
-
- EJECT
-
- ;____Dvc_Controls____
- ;*******************************************************
- ;
- ; 'start_unit'
- ;
- ; Issue a START UNIT Command to the target device
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT start_unit
- start_unit PROC
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
-
- ldy #dib.dvcchar
- lda [dib_ptr],y
- and #removable
- bne @do_it
- rts
-
- @do_it
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- ;
- ; Set Stop Flag
- ;
- lda #$0001
- tsb |stop_bit
- bra start_stop
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'stop_unit'
- ;
- ; Issue a STOP UNIT Command to the target device
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT stop_unit
- stop_unit
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
-
- ldy #dib.dvcchar
- lda [dib_ptr],y
- and #removable
- bne @do_it
- rts
-
- @do_it
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- ;
- ; Set Stop Flag
- ;
- lda #$0001
- trb |stop_bit
- ;
- ; Secondary entry point for START_UNIT
- ; Command
- ;
- EXPORT start_stop
- start_stop
- ;
- ; Set Internal Command Flag
- ;
- dec |internal
- ;
- ; Set Parm Pointer.
- ;
- lda #@start_stop_p
- sta <scsi_mdrvr
- lda #^@start_stop_p
- sta <scsi_mdrvr+2
- ;
- ; Set IMMED Bit
- ;
- lda #immed_loc
- tsb @immed_loc
- ;
- ; It's a Control Call.
- ;
- lda #scsit_cont
- sta |call_type
- ;
- ; Issue the Call
- ;
- jmp |main_drvr
- ;
- ; Data for this call
- ; TEST UNIT READY Command Packet
- ;
- @start_stop_p dc.b $1B ;Command Number
- @immed_loc dc.b $00 ;SCSI Command Flags
- dcb.b 2,$00 ;Reserved
- EXPORT stop_bit
- stop_bit dc.b $00 ;Start/Stop Bit
- dc.b $00 ;Vendor Unique
- dcb.b 6,$00 ;Resrved
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'SET 512 MODE'
- ;
- ; This command is used to tell the device to set it's
- ; block size to 512 mode. This is used for the CD-ROM
- ; Drives as well as any others that may need this
- ; function.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Error Code if any
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if call failed
- ;
- ;*******************************************************
-
- EXPORT set_512_mode
- set_512_mode PROC
-
- ;-------------------------------------------------------------------------------
-
- IF block_dvc = true\
- AND character_dvc = false THEN
- ;
- ; Set try twice flag.
- ;
- dec @try_twice
- ;
- ; Set Internal Command Flag
- ;
- dec |internal
- ;
- ; Set Parm length.
- ;
- lda #end_4_512-\
- data_4_512
- sta <rqst_cnt
- stz <rqst_cnt+2
- ;
- ; Set Parm Pointer.
- ;
- @try_again lda #@set_512_p
- sta <scsi_mdrvr
- lda #^@set_512_p
- sta <scsi_mdrvr+2
- ;
- ; Set Parm Pointer.
- ;
- lda #data_4_512
- sta <buff_ptr
- lda #^data_4_512
- sta <buff_ptr+2
- ;
- ; It's a Control Call.
- ;
- lda #scsit_cont
- sta |call_type
- ;
- ; Issue the Call
- ;
- jsr |main_drvr
- bcc @alles_klar
- ;
- ; Set Parm length.
- ;
- lda #$0000000c
- sta <rqst_cnt
- stz <rqst_cnt+2
-
- inc @try_twice
- beq @try_again
- ;
- ; Restore the values we destroyed
- ;
- @alles_klar stz @try_twice
- php
- pha
- jsr set_our_dp
- pla
- plp
- rts
- ;
- ; Data for this call
- ;
- @try_twice dc.w null
- ;
- ; TEST UNIT READY Command Packet
- ;
- @set_512_p dc.b $15 ;Command Number
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
- ;
- ; Set bit to save these values
- ;
- dc.b $01
-
- ENDIF ;scsi_dtype = direct_acc
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = apple_cd THEN
- ;
- ; Clear bit to save these values
- ;
- dc.b $00
-
- ENDIF ;scsi_dtype = apple_cd
-
- ;-------------------------------------------------------------------------------
-
- dcb.b 3,$00 ;Reserved
- dc.b $00 ;Vendor Unique
- dcb.b 6,$00 ;Resrved
- ;
- ; Data sent durring this call
- ;
- data_4_512 dc.b null
- dc.b $00
- dc.b null
- dc.b $08
- ;number of blocks
- dc.b null
- dc.b $00
- dc.b $00
- dc.b $00
- ;block size
- dc.b null
- dc.b $00
- dc.b $02
- dc.b $00
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = apple_cd THEN
-
- end_4_512
-
- EXPORT select_page_num
- select_page_num dc.b $01 ;Page Number
- dc.b $06 ;Page Length
- dc.b $e4 ;Error Correction Flags
- dc.b $03 ;Retry Count
- dc.b $00 ;Correction Span
- dc.b $00 ;Head Offset Count
- dc.b $00 ;Data Strobe Offset
- dc.b $00 ;Recovery Time Limit
-
- ELSE ;scsi_dtype = apple_cd
-
- ;-------------------------------------------------------------------------------
-
- ;Page 1 Data
- EXPORT select_page_num
- select_page_num dc.b $01 ;Page Number
- dc.b $06 ;Page Length
- dc.b $e4 ;Error Correction Flags
- dc.b $03 ;Retry Count
- dc.b $00 ;Correction Span
- dc.b $00 ;Head Offset Count
- dc.b $00 ;Data Strobe Offset
- dc.b $00 ;Recovery Time Limit
- end_4_512
-
- ENDIF ;scsi_dtype = apple_cd
-
- ;-------------------------------------------------------------------------------
-
- ELSE ;block_dvc = true
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF ;block_dvc = true
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;____Evnt_Support____
- ;*******************************************************
- ;
- ; 'notify_me'
- ;
- ; This routine gets called by the SCSI Manager when
- ; some event occurs that is out of the ordinary.
- ;
- ; Inputs: None Yet
- ;
- ; Outputs: All Regs = Scrambled
- ;
- ; Errors: None Yet
- ;
- ;*******************************************************
-
- EXPORT notify_me
- notify_me PROC
- ;
- ; Vector for the SCSI Manager
- ; to call when an event occurs
- ; that affects my DIB
- ; structures. This could be a
- ; new device online or media
- ; insertion.
- ;
- clc ;Add CODE LATER
- rtl
-
- ENDP
-
- EJECT
-
- ;____Misc_Support____
- ;*******************************************************
- ;
- ; SET_DISK_SW
- ;
- ; This routine checks the validity of the partition
- ; map block currently loaded in the internal buffer.
- ; This need only be called once per device. If the
- ; map is valid, then the carry will be clear. The 'Z'
- ; flag will also be set if this is not the first time
- ; that this routine was called for this device. If
- ; the carry is set, then the map was invalid and the
- ; block count at 'T_DVC_BLOCKS' has been placed in the
- ; DIB pointed to by 'DIB_PTR'. The starting block will
- ; also have been set to null.
- ;
- ; Inputs: <DIB_PTR = DIB Location
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; = Z = 0 if routine called before
- ; = C = 1 if not a partition map
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Only those allowed by the System Service
- ; Call SET_DISKSW.
- ;
- ;*******************************************************
-
- EXPORT set_disk_sw
- set_disk_sw PROC
-
- ;-------------------------------------------------------------------------------
-
- IF block_dvc = true\
- AND character_dvc = false THEN
- ;
- ; Check the removable flag. If the media
- ; is removable, then we will only set the
- ; switch flag and let the status calls do
- ; their thing before this device goes
- ; online. If it is non-removable, then
- ; we need to say that the device is
- ; switched, but also set the online bits.
- ;
- ldy #dib.dvcchar
- lda [dib_ptr],y
- and #removable
- beq @non_removable
- ;
- ; Set the Disk Switched Bit in Status.
- ;
- ldy #dib.dvcflag
- lda [dib_ptr],y
- ora #dvc_switch
- sta [dib_ptr],y
- bra @over1
- ;
- ; Set the Disk Online Bit in Status.
- ;
- @non_removable ldy #dib.dvcflag
- lda [dib_ptr],y
- and #$ffff--\
- dvc_switch--\
- dvc_hardofl
- ora #dvc_online
- sta [dib_ptr],y
- ;
- ; Preserve the World from this.
- ;
- @over1 ldx |gsos_dpage
-
- lda >dev_num,x
- pha
- lda >dib_ptr,x
- pha
- lda >dib_ptr+2,x
- pha
- lda <dev_num
- sta >dev_num,x
- lda <dib_ptr
- sta >dib_ptr,x
- lda <dib_ptr+2
- sta >dib_ptr+2,x
-
- txa
- tcd
-
- jsl set_disksw
- tay
-
- lda |direct_page
- tcd
-
- ldx |gsos_dpage
- pla
- sta >dib_ptr+2,x
- pla
- sta >dib_ptr,x
- pla
- sta >dev_num,x
-
- tya
- cmp #$0001
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; TRASH_VOLUME
- ;
- ; This routine write a non-formatted pattern to block
- ; 2 of the volume whose DIB is [dib_ptr]. This is to
- ; force the OS to re-format or lay down the OS data for
- ; that volume rather than using what is already there
- ; and appears to be valid.
- ;
- ; Inputs: <DIB_PTR = DIB Location
- ; |trash_it = Boolean
- ; 0 = Trash the Volume
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Better be none.
- ;
- ;*******************************************************
-
- EXPORT trash_volume
- trash_volume PROC
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
-
- ;
- ; Should we really trash the volume?
- ;
- lda |trash_it
- beq @dont_trash
- ;
- ; Set Main Driver Pointer to
- ; our data for the command.
- ;
- lda #@cmd_$800A
- sta <scsi_mdrvr
- lda #^@cmd_$800A
- sta <scsi_mdrvr+2
- ;
- ; Set our buffer Pointer to
- ; our data for the command.
- ;
- lda #@destructo_data
- sta <buff_ptr
- lda #^@destructo_data
- sta <buff_ptr+2
- ;
- ; Set length of our data for the
- ; command.
- ;
- lda #block_size
- sta <rqst_cnt
- stz <rqst_cnt+2
- ;
- ; Call Main Driver
- ;
- lda #scsit_cont
- sta |call_type
- ;
- ; Issue the call.
- ;
- jsr check_532_rw
-
- @dont_trash rts
-
- ;
- ; Command Data for this call.
- ;
- @cmd_$800A dc.b $0A
- dc.b $00
- dc.w $0002
- dc.b $01
- dcb.b 7,$00
-
- @destructo_data dcb.b 512,$6c
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'SAVE_DP'
- ;
- ; This routine is only called durring the initial
- ; startup. It saves away the current values on GS/OS
- ; Direct Page so that we can use the space until we
- ; have our own Direct Page.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS
- ; Data Bank = Ours
- ;
- ; Errors: None.
- ;
- ;*******************************************************
-
- EXPORT save_dp
- save_dp PROC
- ;
- ; Check to see if this call was
- ; nested.
- ;
- lda |valid
- bne @exit
- ;
- ; Calculate Source Address.
- ;
- clc
- lda |gsos_dpage
- adc #start_our_zp
- pea $0000
- pha
- ;
- ; Destination Address of temporary
- ; storage
- ;
- pushlong #saved_zp
-
- pushlong #end_our_zp-\ ;Length of the move
- start_our_zp
-
- pushword #move_sinc_dinc
-
- jsl move_info ;Move the data
-
- dec |valid
-
- @exit rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; Move the contents of the first $20 bytes of GS/OS
- ; Direct Page to our Direct Page.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit is not the only
- ; device in this linke that is still
- ; online.
- ;
- ;*******************************************************
-
- EXPORT restore_dp
- restore_dp PROC
- ;
- ; Check to see if this call was
- ; nested.
- ;
- lda |valid
- beq @exit
- ;
- ; Source Address of temporary
- ; storage
- ;
- pushlong #saved_zp
- ;
- ; Calculate Destination Address.
- ;
- clc
- lda |gsos_dpage
- adc #start_our_zp
- pea $0000
- pha
-
- pushlong #end_our_zp-\ ;Length of the move
- start_our_zp
-
- pushword #move_sinc_dinc
-
- jsl move_info ;Move the data
-
- stz |valid
-
- @exit rts
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; Move the contents of the first $20 bytes of GS/OS
- ; Direct Page to our Direct Page.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if Unit is not the only
- ; device in this linke that is still
- ; online.
- ;
- ;*******************************************************
-
- EXPORT set_our_dp
- set_our_dp PROC
- ;
- ; Calculate Source Address.
- ;
- clc
- lda |gsos_dpage
- adc #dev_num
- pea $0000
- pha
- ;
- ; Calculate Destination Address of
- ; our Direct Page that we want.
- ;
- clc
- lda |direct_page
- adc #dev_num
- pea $0000
- pha
-
- pushlong #dib_ptr+4 ;Length of the move
-
- pushword #move_sinc_dinc
-
- jsl move_info ;Move the data
- rts
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'check_532_rw'
- ;
- ; There are a few drives that have been formated with
- ; 512 ($214) bytes per block. These devices work
- ; perfectly fine in single block I/O, padding the end
- ; with 20 bytes in a write, or stripping them for a
- ; read, but when doing a multi-block transaction we
- ; need to account for the 20 bytes between the end of
- ; real data for this block and the beginning of the
- ; next block. Because of this, we will need to build
- ; a data chaining structure that will read or write
- ; 512 bytes of data to the users buffer, followed by
- ; 20 bytes read or written to ROM space. Doing this
- ; will hinder performance and will prevent caching
- ; from working. If these are important to the user,
- ; they can reformat their drive.
- ;
- ; This routine is called in place of calling the Main
- ; Driver. It decides if the call should go via the
- ; normal or 532 method. All Inputs, Outputs and Setup
- ; Structures are the same.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS Direct Page
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT check_532_rw
- check_532_rw PROC
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
-
- ;
- ; Check for 532 byte block.
- ;
- ldy #dib.blksize
- lda [dib_ptr],y
- cmp #$214
- beq @do_532
- jmp |main_drvr
-
- @do_532 jmp munge_532
-
- ;-------------------------------------------------------------------------------
-
- ELSE
-
- jmp |main_drvr
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'munge_532'
- ;
- ; There are a few drives that have been formated with
- ; 512 ($214) bytes per block. These devices work
- ; perfectly fine in single block I/O, padding the end
- ; with 20 bytes in a write, or stripping them for a
- ; read, but when doing a multi-block transaction we
- ; need to account for the 20 bytes between the end of
- ; real data for this block and the beginning of the
- ; next block. Because of this, we will need to build
- ; a data chaining structure that will read or write
- ; 512 bytes of data to the users buffer, followed by
- ; 20 bytes read or written to ROM space. Doing this
- ; will hinder performance and will prevent caching
- ; from working. If these are important to the user,
- ; they can reformat their drive.
- ;
- ; This routine is called in place of calling the Main
- ; Driver. All Inputs, Outputs and Setup Structures
- ; are the same.
- ;
- ; Inputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = Ours
- ; Data Bank = Ours
- ;
- ; Outputs: Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS Direct Page
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT munge_532
- munge_532 PROC
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
-
- ;
- ; Set User's buffer location
- ;
- lda <buff_ptr
- sta |@User_buff
- lda <buff_ptr+2
- sta |@User_buff+2
- ;
- ; Generate a block count.
- ;
- stz @block_cnt
- lda <rqst_cnt+2
- sta @block_cnt+1
- lda <rqst_cnt
- and #$fe00
- cmp <rqst_cnt
- beq @equal_512
-
- lda #drvr_bad_cnt
- sec
- rts
-
- @equal_512 lsr @block_cnt+1
- ror a
- tsb @block_cnt-1
- ;
- ; Adjust users request cnt to reflect
- ; that there are 20 bytes/block more
- ; to transfer than the user requested.
- ; This is done by multiplying the block
- ; count that we just calculated bu $14.
- ;
- ; First preserve the old value.
- ;
- lda <rqst_cnt+2
- sta @rqst_cnt+2
- lda <rqst_cnt
- sta @rqst_cnt
- ;
- ; Now adjust count.
- ;
- lda @block_cnt+2
- sta |scratch0+2
- lda @block_cnt
- sta |scratch0
- ;
- ; x4 first
- ;
- asl |scratch0 ;x2
- asl |scratch0+2
-
- asl |scratch0 ;x2 (x4)
- asl |scratch0+2
- ;
- ; Save the x4.
- ;
- lda |scratch0
- sta |scratch2
- lda |scratch0+2
- sta |scratch2+2
- ;
- ; Finish the x16
- ;
- asl |scratch0 ;x2 (x8)
- asl |scratch0+2
-
- asl |scratch0 ;x2 (x16)
- asl |scratch0+2
- ;
- ; Add the x4 to x16 for x20
- ;
- clc
- lda |scratch0
- adc |scratch2
- sta |scratch0
- lda |scratch0+2
- adc |scratch2+2
- sta |scratch0+2
- ;
- ; Add the x20 to the original
- ; request count.
- ;
- clc
- lda |scratch0
- adc <rqst_cnt
- sta <rqst_cnt
- lda |scratch0+2
- adc <rqst_cnt+2
- sta <rqst_cnt+2
- ;
- ; Preserve the data pointer currently
- ; used in the DIB and replace it with
- ; a pointer to our 532 byte block
- ; Data Chaining instructions.
- ;
- clc
- ldy #dib.trx_ptr
- lda [dib_ptr],y
- sta |dib_data_struct
-
- lda #@munger_DC
- sta [dib_ptr],y
-
- ldy #dib.trx_ptr+2
- lda [dib_ptr],y
- sta |dib_data_struct+2
-
- lda #^@munger_DC
- sta [dib_ptr],y
- ;
- ; Preserve the Block size and replace
- ; it with $0214
- ;
- lda <blk_size
- sta @blk_size
- lda #$0214
- sta <blk_size
- ;
- ; Issue the call.
- ;
- jsr |main_drvr
- ;
- ; Preserve the result.
- ;
- pha
- php
- ;
- ; Restore the Block size.
- ;
- lda @blk_size
- sta <blk_size
- ;
- ; Restore DIB's data pointer.
- ;
-
- ldy #dib.trx_ptr
- lda |dib_data_struct
- sta [dib_ptr],y
-
- ldy #dib.trx_ptr+2
- lda |dib_data_struct+2
- sta [dib_ptr],y
- ;
- ; Restore the original request count.
- ;
- lda @rqst_cnt+2
- sta <rqst_cnt+2
- lda @rqst_cnt
- sta <rqst_cnt
- ;
- ; Restore state of the call's exit.
- ;
- plp
- pla
- ;
- ; Exit.
- ;
- rts
- ;
- ; Temp Storage area.
- ;
- @rqst_cnt dc.l null
- @blk_size dc.w null
-
- @munger_DC ;
- ; Data Chaining Structure.
- ;
- @User_buff dc.l $00000000 ;Users Buffer Space
- dc.l $00000200 ;Request Count
- dc.l $00000200 ;Add to buffer at each pass
- dc.l $00000000 ;Reserved.
-
- dc.l $00ff0600 ;Location for spare bytes (ROM)
- dc.l $00000014 ;Number of bogus bytes
- dc.l $00000000 ;Leave buffer pointer alone
- dc.l $00000000 ;Reserved.
-
- dc.l $ffffffff ;Looping Command
- @block_cnt dc.l $00000000 ;Block Count
- dc.l $00000000-2 ;Go Back 2 commands
- dc.l $00000000 ;Reserved
-
- dc.l $00000000 ;DCStop Command
- dc.l $00000000 ;DCStop Command
- dc.l $00000000 ;DCStop Command
- dc.l $00000000 ;DCStop Command
-
- dc.l $00000000 ;Safety space
-
- ;-------------------------------------------------------------------------------
-
- ELSE
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'divide'
- ;
- ; This routine divides a 16 bit number stored in
- ; 'divsor' into the 32 bit number stored in 'divend'.
- ; The result will be in 'result' if no error occured.
- ; If 'divend' is not an integral multiple of 'divsor'
- ; an error will be returned.
- ;
- ; Inputs: 'divsor' = 16 bit number
- ; 'divend' = 32 bit number
- ; 'max_blk_cnt' = Max Result Allowed
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS Direct Page
- ; Data Bank = Ours
- ;
- ; Outputs: 'result' = result of division
- ; Acc = Error Code if Carry Set
- ; 'max_blk_cnt' = null if no error
- ; Intact if an error is returned
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS Direct Page
- ; Data Bank = Ours
- ;
- ; Errors: Carry set if non-integral result
- ;
- ;*******************************************************
-
- EXPORT divide
- divide PROC
-
- ;-------------------------------------------------------------------------------
-
- IF block_dvc = true\
- AND character_dvc = false THEN
- ;
- ; Clear Result field
- ;
- stz |result
- stz |result+2
- ;
- ; 32 bits in result.
- ;
- ldx #32-1
- ;
- ; Make 'divsor' an odd value.
- ; This is nothing more than
- ; deviding both numbers by 16
- ; until 'divsor' is an odd value.
- ; If any bits roll out of 'divend'
- ; then this was an incorrect call.
- ;
- @div16_loop lda |divsor
- cmp #block_size ;Special Case /block_size
- bne @not_512
- lda |divend
- and #block_size-1
- bne @error
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
- ;
- ; Quick Divide by block_size
- ;
- lda |divend+3
- and #$00ff
- lsr a
- sta |result+2
-
- lda |divend+1
- ror a
- sta |result
-
- jmp @chk_rslt
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = apple_cd THEN
- ;
- ; Quick Divide by $0200
- ;
- lda |divend+3
- and #$00ff
- lsr a
- sta |result+2
-
- lda |divend+1
- ror a
- sta |result
-
- jmp @chk_rslt
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- @not_512 and #bit_0
- bne @do_divide
- lsr |divsor
- lsr |divend+2
- ror |divend
- bcc @div16_loop
- bra @error
- ;
- ; Main division loop. We will
- ; continue to divide the divsor
- ; by 16 until finished. Each
- ; time that divsor becomes odd,
- ; we will subtract divend and
- ; roll a bit into the high end
- ; of result.
- ;
- @do_divide lda |divend
- and #bit_0
- clc ;We must clear the carry incase
- beq @do_div16 ;the branch is taken.
- ;
- ; We are odd. Do the subtraction.
- ;
- sec
- lda |divend
- sbc |divsor
- sta |divend
- lda |divend+2
- sbc #$0000
- sta |divend+2
- bcc @error ;If this is taken, bad data.
- ;
- ; Divide both the divsor and
- ; results by 16. The carry will
- ; roll into the reult from the
- ; high bit end.
- ;
- @do_div16 php
- lsr |divend+2
- ror |divend
- plp
- @clean_up ror |result+2
- ror |result
- ;
- ; Have we done 32 bits yet?
- ;
- dex
- bmi @chk_rslt ;Yes.
- ;
- ; No we havent. If divsor is
- ; non-zero then do next itteration.
- ; If it is = zero then clean up
- ; result and exit.
- ;
- lda |divend+2
- ora |divend
- bne @do_divide
- ;
- ; Clean up Result.
- ;
- clc
- bra @clean_up
- ;
- ; Here for bcs offset.
- ;
- @error sec
- lda #drvr_bad_cnt
- rts
- ;
- ; Check to see if the result is within
- ; the max.
- ;
- @chk_rslt lda |max_blk_cnt
- ora |max_blk_cnt+2
- beq @out
-
- sec
- lda |max_blk_cnt
- sbc |result
- sta @temp
- lda |max_blk_cnt+2
- sbc |result+2
- bge @clean
- ;
- ; Exit
- ;
- sec
- lda #drvr_bad_parm
- rts
-
- @clean stz |max_blk_cnt
- stz |max_blk_cnt+2
- @out clc
- rts
- ;
- ; Data Area.
- ;
- @temp dc.w null
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- ;*******************************************************
- ;
- ; 'calc_bytes'
- ;
- ; This routine Multiplies a 16 bit number stored in
- ; 'm_blk_size' by a 32 bit number stored in 'm_blk_cnt'.
- ; The result will be in 'm_rslt'.
- ;
- ; Inputs: 'm_blk_size'= 16 bit Block Size
- ; 'm_blk_cnt' = 32 bit Block Count
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS Direct Page
- ; Data Bank = Ours
- ;
- ; Outputs: 'm_rslt' = result of division
- ; Acc = Unspecified
- ; Y register = Unspecified
- ; X register = Unspecified
- ; P register = 0=M=X=e
- ; Direct Page = GS/OS Direct Page
- ; Data Bank = Ours
- ;
- ; Errors: None
- ;
- ;*******************************************************
-
- EXPORT calc_bytes
- calc_bytes PROC
-
- ;-------------------------------------------------------------------------------
-
- IF block_dvc = true\
- AND character_dvc = false THEN
- ;
- ; Clear Result field
- ;
- stz |m_rslt
- stz |m_rslt+2
- ;
- ; Check 'm_blk_size' against the block
- ; size for this device. If it is Equal,
- ; the do cheap processing. Otherwise do
- ; full multiply logic.
- ;
- @div16_loop lda |m_blk_size
- cmp #block_size ;Special Case *block_size
- bne @not_512
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = direct_acc THEN
- ;
- ; Quick Multiply by $0200
- ;
- lda |m_blk_cnt
- asl a
- sta |m_rslt+1
-
- lda |m_blk_cnt+2
- and #$007f
- rol a
- ora |m_rslt+3 ;Watch out for that +4 value.
- sta |m_rslt+3 ;It doesn't belong to us.
-
- jmp @clean
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- IF scsi_dtype = apple_cd THEN
- ;
- ; Quick Multiply by $0200
- ;
- lda |m_blk_cnt
- asl a
- sta |m_rslt+1
-
- lda |m_blk_cnt+2
- and #$007f
- rol a
- ora |m_rslt+3 ;Watch out for that +4 value.
- sta |m_rslt+3 ;It doesn't belong to us.
-
- jmp @clean
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- @not_512
- ;
- ; Actual Multiply Loop.
- ;
- lsr |m_blk_size
- bcc @shift_cnt ;Don't Add this one.
- ;
- ; Add in Current Byte Count.
- clc
- lda |m_rslt
- adc |m_blk_cnt
- sta |m_rslt
- lda |m_rslt+2
- adc |m_blk_cnt+2
- sta |m_rslt+2
- ;
- ; Multiply Count by 2.
- ;
- @shift_cnt asl |m_blk_cnt
- rol |m_blk_cnt+2
-
- lda |m_blk_size
- bne @not_512 ;only do till 0 ( <16 times )
- ;
- ; Clean Exit.
- ;
- @clean clc
- rts
-
- ELSE
-
- ;-------------------------------------------------------------------------------
-
- lda #null
- clc
- rts
-
- ENDIF
-
- ;-------------------------------------------------------------------------------
-
- ENDP
-
- EJECT
-
- END